Содержание | Предыдущий | Следующий | Индекс

21.9 Класс java.util.Random

Каждый экземпляр класса Random служит отдельным, независимым псевдослучайным генератором примитивных значений.

public class Random {
	protected long seed;
	protected double nextNextGaussian;
	protected boolean haveNextNextGaussian = false;
	public Random();
	public Random(long seed);
	public void setSeed(long seed);
	protected int next(int bits);
	public int nextInt();
	public long nextLong();
	public float nextFloat();
	public double nextDouble();
	public double nextGaussian();
}
Если два Random объекты создаются с тем же самым семенем, и та же самая последовательность вызовов метода делается для каждого, они генерируют и возвратят идентичные последовательности чисел во всех реализациях Java. Чтобы гарантировать это свойство, определенные алгоритмы определяются для класса Random. Реализации Java должны использовать все алгоритмы, показанные здесь для класса Random, ради абсолютной мобильности кода Java. Однако, подклассы класса Random разрешаются использование другие алгоритмы, пока они придерживаются общих контрактов для всех методов.

Алгоритмы реализуются классом Random используйте переменные с тремя состояниями, которые являются protected. Они также используют a protected служебный метод, который на каждом вызове может предоставить до 32 псевдобеспорядочно сгенерированных битов.

21.9.1 protected long seed;

Переменная используется методом next (§21.9.7), чтобы содержать состояние генератора псевдослучайного числа.

21.9.2 protected double nextNextGaussian;

Переменная используется методом nextGaussian (§21.9.12), чтобы содержать предварительно вычисленное значение, которое будет поставлено тем методом в следующий раз, это вызывают.

21.9.3 protected boolean haveNextNextGaussian = false;

Переменная используется методом nextGaussian (§21.9.12), чтобы отследить то, предварительно ли это вычислило и спрятало следующее значение, которое будет поставлено тем методом.

21.9.4 public Random()

Этот конструктор инициализирует недавно создаваемый Random генератор чисел при использовании текущего времени дня (§20.18.6) как семя.

public Random() { this(System.currentTimeMillis()); }

21.9.5 public Random(long seed)

Этот конструктор инициализирует недавно создаваемый Random генератор чисел при использовании параметра seed как семя.


public Random(long seed) { setSeed(seed); }

21.9.6 public void setSeed(long seed)

Общий контракт setSeed это, это изменяет состояние этого объекта генератора случайных чисел, чтобы быть в точно том же самом состоянии, как будто это было только что создано с параметром seed как семя.

Метод setSeed реализуется классом Random следующим образом:


synchronized public void setSeed(long seed) {
	this.seed = (seed ^ 0x5DEECE66DL) & ((1L << 48) - 1);
	haveNextNextGaussian = false;
}
Реализация setSeed классом Random оказывается, использует только 48 битов данного семени. Вообще, однако, метод переопределения может использовать все 64 бита длинного параметра как значение семени.

[В определенных ранних версиях Java, setSeed метод, отказавший, чтобы сбросить значение haveNextNextGaussian к false; этот дефект мог привести к отказу произвести повторимое поведение.]

21.9.7 protected int next(int bits)

Общий контракт next это, это возвращается int значение и если биты параметра между 1 и 32 (включительно), тогда то, что много битов младшего разряда возвращенного значения будут (приблизительно) независимо выбранными битовыми значениями, каждое из которых (приблизительно), одинаково вероятно, будет 0 или 1.

Метод next реализуется классом Random следующим образом:


synchronized protected int next(int bits) {
	seed = (seed * 0x5DEECE66DL + 0xBL) & ((1L << 48) - 1);
	return (int)(seed >>> (48 - bits));
}
Это - линейный congruential генератор псевдослучайного числа, как определено Д. Х. Лехмером и описало Дональдом Э. Нутом в Искусстве Программирования, Объем 2: получисловые Алгоритмы, разделите 3.2.1.

21.9.8 public int nextInt()

Общий контракт nextInt тот int значение псевдобеспорядочно сгенерировано и возвращено. Все возможные int значения производятся с (приблизительно) равной вероятностью.

Метод setSeed реализуется классом Random следующим образом:

public int nextInt() {  return next(32); }

21.9.9 public long nextLong()

Общий контракт nextLong тот long значение псевдобеспорядочно сгенерировано и возвращено. Все возможные long значения производятся с (приблизительно) равной вероятностью.

Метод setSeed реализуется классом Random следующим образом:


public long nextLong() {
	return ((long)next(32) << 32) + next(32);
}

21.9.10 public float nextFloat()

Общий контракт nextFloat тот float значение, выбранное (приблизительно) однородно из диапазона 0.0f (включительно) к 1.0f (монопольный), псевдобеспорядочно сгенерирован и возвращен. Все возможные float значения формы, где м. является положительным целым числом меньше чем, производятся с (приблизительно) равной вероятностью.

Метод setSeed реализуется классом Random следующим образом:


public float nextFloat() {
	return next(24) / ((float)(1 << 24));
}
Преграда "приблизительно" используется в предшествующем описании только потому, что next метод является только приблизительно несмещенным источником независимо выбранных битов. Если бы это был совершенный источник или в произвольном порядке выбранные биты, то показанный алгоритм выбрал бы float значения от установленного диапазона с совершенной однородностью.

[В ранних версиях Java результат был неправильно вычислен как:

	return next(30) / ((float)(1 << 30));
Это, могло бы казаться, было бы эквивалентно, если бы не лучше, но фактически это представляло небольшую неоднородность из-за смещения в округлении чисел с плавающей точкой: было немного более вероятно, что бит младшего разряда мантиссы будет 0 чем это это было бы 1.]

21.9.11 public double nextDouble()

Общий контракт nextDouble тот double значение, выбранное (приблизительно) однородно из диапазона 0.0d (включительно) к 1.0d (монопольный), псевдобеспорядочно сгенерирован и возвращен. Все возможные float значения формы, где м. является положительным целым числом меньше чем, производятся с (приблизительно) равной вероятностью.

Метод setSeed реализуется классом Random следующим образом:


public double nextDouble() {
	return (((long)next(26) << 27) + next(27))
				/ (double)(1L << 53);
}
Преграда "приблизительно" используется в предшествующем описании только потому, что next метод является только приблизительно несмещенным источником независимо выбранных битов. Если бы это был совершенный источник или в произвольном порядке выбранные биты, то показанный алгоритм выбрал бы double значения от установленного диапазона с совершенной однородностью.

[В ранних версиях Java результат был неправильно вычислен как:


	return (((long)next(27) << 27) + next(27))
				/ (double)(1L << 54);
Это, могло бы казаться, было бы эквивалентно, если бы не лучше, но фактически это представляло большую неоднородность из-за смещения в округлении чисел с плавающей точкой: было в три раза более вероятно, что бит младшего разряда мантиссы будет 0 чем это это было бы 1! Эта неоднородность, вероятно, не имеет значения очень практически, но мы боремся за совершенство.]

21.9.12 public double nextGaussian()

Общий контракт nextGaussian тот double значение, выбранное из (приблизительно) обычного нормального распределения со средним значением 0.0 и стандартное отклонение 1.0, псевдобеспорядочно сгенерирован и возвращен.

Метод setSeed реализуется классом Random следующим образом:


synchronized public double nextGaussian() {
	if (haveNextNextGaussian) {
		haveNextNextGaussian = false;
		return nextNextGaussian;
	} else {
		double v1, v2, s;
		do { 
			v1 = 2 * nextDouble() - 1; 	// between -1.0 and 1.0
			v2 = 2 * nextDouble() - 1; 	// between -1.0 and 1.0
			s = v1 * v1 + v2 * v2;
		} while (s >= 1);
		double norm = Math.sqrt(-2 * Math.log(s)/s);
		nextNextGaussian = v2 * norm;
		haveNextNextGaussian = true;
		return v1 * norm;
	}
}
Это использует полярный метод Г. Э. П. Поле, М. Э. Мюллер, и Г. Марсэглия, как описано Дональдом Э. Нутом в Искусстве Программирования, Объем 2: получисловые Алгоритмы, разделите 3.4.1, подраздел C, алгоритм П. Ноут, что это генерирует два независимых значения за счет только одного звонка Math.log и один звонок Math.sqrt.


Содержание | Предыдущий | Следующий | Индекс

Спецификация языка Java (HTML, сгенерированный Блинчиком "сюзет" Pelouch 24 февраля 1998)
Авторское право © Sun Microsystems, Inc 1996 года. Все права защищены
Пожалуйста, отправьте любые комментарии или исправления к doug.kramer@sun.com



Spec-Zone.ru - all specs in one place



free hit counter