Приложение:
Взгляните на исходный код java.util.Random
, включенный в дистрибутив Oracle JDK 7 ( "Copyright (c) 1995, 2010, Oracle и / или его филиалы. Все права защищены. ORACLE PROPRIETARY / CONFIDENTIAL. Использование в соответствии с условиями лицензии ") показывает этот простой код:
class Random {
public float nextFloat() {
return next(24) / ((float)(1 << 24));
}
protected int next(int bits) {
long oldseed, nextseed;
AtomicLong seed = this.seed;
do {
oldseed = seed.get();
nextseed = (oldseed * multiplier + addend) & mask;
} while (!seed.compareAndSet(oldseed, nextseed));
return (int)(nextseed >>> (48 - bits));
}
}
Таким образом, для nextFloat()
:
- Возьмите "случайное целочисленное значение" между 0 и 2 ^ 24-1 (или, скорее, случайный 24-битный битовый шаблон, интерпретируемый как целочисленное значение),
- Преобразовать его в float (в Java «float» должен быть 32-битной плавающей точкой IEEE 724, которая может представлять до 2 ^ 24 без потери точности, и, таким образом, это будет значение между 0 и 1.6777215E7)
- Затем разделите его на представление с плавающей точкой 2 ^ 24, снова просто представимое без потери точности как 1.6777216E7. 2 ^ 24 + 1 = 16777217 упадет до 1.6777216E7, когда будет вынужден быть плавающим. В коде это действительно должно быть константой. Эй, Солнце, циклы не растут на деревьях !!
- Результатом деления является плавающее число в [0.0 .. 0.99999994] (правильный результат деления будет около 0.999999940395355224609375) со всеми, как мне кажется, всеми возможными значениями с плавающей запятой IEEE 724 между одинаково возможными ».
См. Также IEEE с плавающей точкой и Арифметика с плавающей точкой на JVM .
Комментарии Javadoc для `next ():
<code>/**
* Generates the next pseudorandom number. Subclasses should
* override this, as this is used by all other methods.
*
* <p>The general contract of {@code next} is that it returns an
* {@code int} value and if the argument {@code bits} is between
* {@code 1} and {@code 32} (inclusive), then that many low-order
* bits of the returned value will be (approximately) independently
* chosen bit values, each of which is (approximately) equally
* likely to be {@code 0} or {@code 1}. The method {@code next} is
* implemented by class {@code Random} by atomically updating the seed to
* <pre>{@code (seed * 0x5DEECE66DL + 0xBL) & ((1L << 48) - 1)}
* и возвращение
*
{@code (int)(seed >>> (48 - bits))}.
*
* Это линейный конгруэнтный генератор псевдослучайных чисел, так как
* определено Д. Х. Лемером и описано Дональдом Кнутом в
*
Искусство компьютерного программирования, Том 3:
*
Получисленные алгоритмы , раздел 3.2.1.
*
* @парам биты случайные биты
* @ вернуть следующее псевдослучайное значение из этого случайного числа
* последовательность генератора
* @ с 1.1
* /
Комментарии Javadoc для nextFloat()
:
<code>/**
* Returns the next pseudorandom, uniformly distributed {@code float}
* value between {@code 0.0} and {@code 1.0} from this random
* number generator's sequence.
*
* <p>The general contract of {@code nextFloat} is that one
* {@code float} value, chosen (approximately) uniformly from the
* range {@code 0.0f} (inclusive) to {@code 1.0f} (exclusive), is
* pseudorandomly generated and returned. All 2<font
* size="-1"><sup>24</sup></font> possible {@code float} values
* of the form <i>m x </i>2<font
* size="-1"><sup>-24</sup></font>, where <i>m</i> is a positive
* integer less than 2<font size="-1"><sup>24</sup> </font>, are
* produced with (approximately) equal probability.
*
* <p>The method {@code nextFloat} is implemented by class {@code Random}
* as if by:
* <pre> {@code
* public float nextFloat() {
* return next(24) / ((float)(1 << 24));
* }}
*
*
Хеджирование "приблизительно" используется только в предыдущем описании.
* потому что следующий метод является лишь приблизительно непредвзятым источником
* независимо выбранные биты. Если бы это был идеальный источник случайно
* выбранные биты, тогда показанный алгоритм выберет {@code float}
* значения из указанного диапазона с идеальной однородностью.
* [В ранних версиях Java результат был неверно рассчитан как:
*
{@code
* return next(30) / ((float)(1 << 30));}
* Это может показаться эквивалентным, если не лучше, но на самом деле это
* введена небольшая неравномерность из-за смещения в округлении
* чисел с плавающей точкой: было немного более вероятно, что
* младший бит значения и будет 0, чем то, что будет 1.]
*
* @ возврат следующего псевдослучайного, равномерно распределенного {@code float}
* значение между {@code 0.0} и {@code 1.0} из этого
* последовательность генератора случайных чисел
* /