2010-06-17 4 views
15

Просто из любопытства, может ли Math.random() когда-либо быть нулевым?Может ли случайная функция Java быть нулевой?

Например, если бы я иметь:

while (true){ 
    if (Math.random() == 0) 
    return 1; 
} 

ли я когда-нибудь на самом деле получить отдачу от одного? Также существует ошибка округления, потому что Math.random() возвращает double.

Я спрашиваю, потому что мой профессор CS заявил, что random() идет от 0 до 1 включительно, и я всегда думал, что это эксклюзивно.

+5

Был ли ваш профессор СС, говорящий о Java, или, скорее, о чисто математической случайной функции с равным распределением? Поскольку такая функция для действительных чисел колеблется от 0 до 1, не имеет никакой вероятности для 0. Также не для 1. И не для 0,5: вероятность может быть назначена только интервалу. Но это, конечно, неверно для дискретного диапазона чисел, как у нас здесь, в Java ... (я уверен, что он имел в виду;) –

+0

Просто проверьте документацию для Math.random(), он укажет, включен ли он или эксклюзивным. –

+0

Здесь нет ошибки округления.Вы просто получите «double» с 53 равномерно распределенными псевдослучайными битами в своей мантиссе. – Joey

ответ

21

Согласно the documentation, «Возвращает двойное значение с положительным знаком, большим или равным 0,0 и менее 1,0». Это означает, что он может быть равен нулю.

Hank wrote, его is эксклюзивный на верхней границе (никогда не может быть 1), так что, возможно, именно здесь ваше замешательство происходит из :-).

9

В зависимости от того, какую нотацию вы предпочитаете, она включает в себя ноль, исключая один, например, [0, 1) или 0 <= x < 1.

0

От http://java.sun.com/javase/6/docs/api/java/lang/Math.html

случайной() возвращает двойное значение с положительным знаком, превышающим или равным 0,0 и менее 1,0.

Да, он может быть равен нулю, но не 1. Иными словами, предпочитают документацию Java над профессором CS =)

1

Math.random() является documented вернуть «двойное значение с положительным знаком, больше или равна 0,0 и меньше 1,0» То есть, включая 0.0, но без учета 1,0

5

В теории , он может вернуть значение ноль.

На практике вам, возможно, придется подождать очень долгое время, чтобы получить точно ноль. Если генератор случайных чисел хорошо реализован, он имеет не менее 56 бит внутреннего состояния (иначе все биты возвращаемого результата не будут случайными). И это означает, что если распределение значений, созданных случайным, является плоским, то у вас есть максимум один шанс в 2^56 вернуть значение, все биты которого равны нулю. Это примерно 10^-19. Я бы не затаил дыхание.

(Другие по праву отметили, что, как задокументировано, теоретически [и предположительно на практике] оно не может вернуть значение 1.0).

+0

Вы можете сделать тот же случай для любой комбинации из 56 бит внутреннего состояния. Если генератор случайных чисел хорошо реализован, вероятность возврата нуля должна быть такой же, как и любой другой двойной диск. –

+0

@ Гилберт: Согласен, но вопрос был конкретно «может ли он быть нулевым?» –

+0

Java использует 48-битный LCG, из которых используются только 32 бита. Это также отмечается в документации для 'nextLong()', которая просто * не может * генерировать все возможные значения 'long'. То же самое происходит (очевидно) для 'double's. – Joey

1

также возможно, в совместимом реализации JRE, что он никогда не возвращает 0.

+2

также возможно, учитывая действительно случайный генератор и из-за характера случайности, что в соответствии с реализацией JRE он ВСЕГДА возвращает 0. –

+0

@Stephen: прочитайте Javadocs (которые для стандартной библиотеки считаются частью Спецификация). Любая реализация 'Math.random()' * должна * использовать 'java.util.Random', который по очереди * должен быть * конкретным LCG. – Joey

+0

@Johannes: Я прочитал javadocs и связался с ними в своем ответе. Моя точка зрения, относящаяся к ответу на неопровержимый ответ, заключается в том, что, хотя это правда, возможно *, что 0.0 никогда не возвращается, также возможно, что 0.0 всегда * возвращается *. Чтобы быть совместимым, должно быть возможно любое значение * x *, где будет возвращено 0.0 <= * x * <1.0, включая невероятные случаи, когда 0 никогда не возвращается или 0 всегда возвращается. Я впервые прочитал заявление неприемлемого как «вы могли бы написать совместимую JRE, которая никогда не вернет 0.» что неверно, но * невероятный случай, когда 0 никогда не возвращается *, является правильным. –

10

Вполне возможно, что он никогда не вернется в точности равна нулю.Включенный Java PRNG - это 48-битный LCG, из которого только 32 бит используются. Для всех 53 битов double мантисса должно быть нулевое значение, вам понадобится по крайней мере один вызов next(), где верхние 32 бита равны нулю, а другая, где большинство из них. (Если я не ошибаюсь, я бы сказал, что этого никогда не случится с тем, как работает генератор, но уже поздно, я устал, и я не буду много на него накладывать).

в документации метода явно указывается, как получены случайные числа, также мало возможностей для других реализаций среды выполнения Java для получения разных результатов. Договор может сказать, что номер, который вы получаете, - от [0, 1). Но на практике существует довольно много значений, которые вы никогда не будете бить (потому что вам нужны два последовательных значения от генератора, которые приводят к линейной зависимости между последовательными значениями - всего 48 бит состояния. Вы не можете генерировать все разные 53-битные комбинации - по крайней мере, не так, как это сделано.).

Конечно, поскольку Math.random() автоматически семян статического Random экземпляра, мы могли бы также рассмотреть семена здесь, которые может нужно быть очень специфичны для теста, чтобы работать. И это может означать, что этот точный момент времени может быть несколько десятилетий или тысяч лет.

+0

+1 Я всегда задавался вопросом, смогу ли я когда-нибудь получить нуль ... – mikera

+0

В качестве практического контрпримера Angs [answer below] (http://stackoverflow.com/a/4371484/733345) показывает конкретное состояние PRNG где генератор будет возвращать именно эту комбинацию 'next()' s. – Joe

35

Да, это действительно может быть. Math.random() создает глобальный java.util.Random -генератор с посевом (System.currentTimeMillis()^0x5DEECE66DL) & ((1L << 48) - 1) и звонит nextDouble(). Если его семя достигнет состояния 107048004364969L (и он будет, так как java.util.Random имеет полный период), в следующем double будет 0.0. Хотя с неудачей вы могли закончиться неправильным соотношением в цикле, потому что Random.nextDouble() продвигает состояние дважды. С небольшим количеством неудач вы могли бы генерировать 2^47 случайных чисел до того, как цикл завершится, так как я не нашел никаких других семян, которые дают 0.0.

Семена авансуются как seed = (seed * 0x5DEECE66DL + 0xBL) & ((1L << 48) - 1); и удваиваются с использованием 26 и 27 верхних бит двух последовательных значений посевного материала. В этом примере два следующих значения начального значения будут равны 0L и 11L.

Если вам удалось создать глобальный генератор с System.currentTimeMillis()==107038380838084L, ваш код немедленно возвращается. Вы можете смоделировать с:

java.util.Random k = new java.util.Random(107038380838084L); System.out.println(k.nextDouble()==0);

+8

И, если вы считаете, что в следующей попытке кажется, что это слишком подозрительно, чтобы получить нуль, используйте 'new java.util.Random (164311266871034L)', и вы ударите его двумя попытками. Или 'new java.util.Random (240144965573432L)', и три попытки. Или 'new java.util.Random (881498)', и вы получите нуль после 376050 вызовов 'nextDouble'. – cayhorstmann

+0

Это должен быть принятый ответ. В вопросе задается запрос 'Math.random' java, который (при первом вызове) создает один новый генератор псевдослучайных чисел, точно так же, как если бы выражение' new java.util.Random() ', которое, в свою очередь, используется как« Random .nextDouble() 'после этого для всех вызовов' Math.random() '. 'nextDouble()' работает как: 'return (((long) next (26) << 27) + next (27))/(double) (1L << 53);' (и неправильно в ранних версиях java as : 'return (((long) next (27) << 27) + next (27))/(double) (1L << 54);'). Здесь 'next' возвращает запрошенные наивысшие биты' (int) (seed >>> (48 бит)) '. – GitaarLAB

1

Это теоретически возможно math.random() возвращает нулевое значение, но в реальном мире, вы можете рассчитывать на это практически никогда не происходит.

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

Но более непосредственно, это практически эксклюзивно в обоих направлениях.

+0

Теоретически невозможно, но вполне возможно. См. Ответ, полученный от @Angs и комментариев. –

+0

Я запускал его в течение месяца один раз, никогда не получал нуль. – Guus

Смежные вопросы