2011-12-20 2 views
2

Что касается предоставления long семян java.util.Random, если я создам экземпляр объекта один раз, кажется, что если я просто возьму время как семя, которое будет удовлетворительным для жизни программы, что для моего Цель означает, что результат серии вызовов nextDouble() выглядит случайным.оптимальная Java Случайное семя

Предположим из соображений простоты кода, я создаю экземпляр Random, используйте его несколько раз, затем повторно создайте экземпляр и повторите. Если семя предоставляется аналогично, семена будут похожими и увеличиваться, потому что они основаны на времени. Увеличение будет небольшим по сравнению со значением, если это количество секунд с 1 января 1970 года. (Редактировать: этот вопрос был задан в 2011 году.)

Если я подключу вывод nextDouble(), экземпляр Random с неслучайным посевом, основанным на времени, вызывает появление тонкой структуры в составной цепочке вывода от nextDouble(). Другой способ сформулировать этот вопрос: нужно ли семя равномерно из набора long.

ответ

7

Вероятно, вы столкнетесь с такой ситуацией, когда на самом деле им будет присвоено одно и то же семя, особенно если они созданы в той же миллисекунде. Некоторые машины имеют разрешение до 15 миллисекунд или более, поэтому это становится еще более серьезной проблемой.

Один из способов обойти это, чтобы использовать Math.random(). Он использует случайный экземпляр системы, который только когда-либо создается при первом запуске. Я не верю, что у вас есть доступ к базовому экземпляру, поэтому вы не можете использовать его для получения nextInt(), но вы можете использовать Math.random() для удвоений или если вы действительно хотите свой собственный объект Random, получите double от Math.random(), преобразуйте его биты в long и используйте это long в качестве семени для вашего нового Random.

Oracle docs for random можно найти here.

// create new random with seed from system random 
Random r = new Random(Double.doubleToLongBits(Math.random())); 
+1

Ничего себе, спасибо Google. Вы связали меня с документацией 1.4.2. Видимо, у вас не было записки о том, что Java 7 отсутствует? – corsiKa

+0

У меня появилась привычка добавлять java6 во все мои поисковые запросы Google для Java :-) Во всяком случае, обновите ссылку java6, по крайней мере. – paxdiablo

+0

Возможно, вы могли бы объяснить, как это лучше, чем случайный по умолчанию. ;) (см. мой ответ) –

2

Это зависит от генератора, конечно, но, по моему опыту, небольшое изменение в семени оказывает большое влияние на значения, которые генерируются.

Его можно обнаружить с небольшим количеством работы, но если вы не делаете высококачественную статистическую работу или криптографию, это не будет иметь особого значения.

В любом случае, если вы были в этом типе домена, вы бы поколение аппаратных средств на основе случайных чисел, вполне возможно, используя что-то вроде 3 кельвина фонового излучения для источника :-)

+2

Или тролль, который сидит в пещере, кричащий «Девять. Девять. Девять. Девять. Девять». Это проблема со случайным, вы никогда не сможете сказать! – corsiKa

+1

Попробуйте «Случайное случайное = новое Случайное (441287210); для (int i = 0; i <10; i ++) System.out.print (random.nextInt (10) +" "); }' prints '1 1 1 1 1 1 1 1 1 1' –

+0

И, если вы продолжаете идти, вы начнете получать разные цифры. Я не совсем уверен в вашей точке, @Peter, если только это не иллюстрирует интересное свойство выражения, используемого в Java PRNG, поскольку '1 1 1 1 1 1 1 1 1 1' имеет тот же probab как '3 1 4 1 5 9 2 6 5 3' или' 2 7 1 8 2 8 1 8 2 8'. – paxdiablo

4

The автоматически созданное случайное семя использует System.nanoTime и счетчик, чтобы обеспечить его всегда разные. ИМХО, Там нет необходимости играть с семенами, чтобы улучшить хаотичности

public Random() { 
    this(seedUniquifier()^System.nanoTime()); 
} 

private static long seedUniquifier() { 
    // L'Ecuyer, "Tables of Linear Congruential Generators of 
    // Different Sizes and Good Lattice Structure", 1999 
    for (;;) { 
     long current = seedUniquifier.get(); 
     long next = current * 181783497276652981L; 
     if (seedUniquifier.compareAndSet(current, next)) 
      return next; 
    } 
} 

Random использует 48 битные посевной и повторяется каждые 2^48 вызовов, что означает, что не может производить все возможное long или double значения.

Мессинг с семенем звучит немного как тройные случайные стратегии, которые на самом деле не помогают. http://thedailywtf.com/Articles/Random-Char-and-TriplyRandom-Double.aspx

Если вы хотите увеличить случайность, используйте SecureRandom, который не дает такую ​​же случайную последовательность, даже если вы даете ей семя 1 каждый раз.Это может привести к возникновению всех возможных значений long и double.

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