2017-02-12 15 views
0

Я пытаюсь создать случайное число с использованием заданной даты для создания хороших псевдослучайных чисел в Java. Я решил использовать класс Calendar и считать миллисекунды в день. Это работало в некоторой степени, но я могу получить только другое случайное значение, когда я запускаю программу. Запуск его еще раз в программе просто даст мне тот же номер. Я использую Thread.sleep(), чтобы убедиться, что есть реальная разница во времени, но я все равно получаю одинаковые номера. Heres мой метод, который я называю (из другого класса)Ошибка с классом календаря и генерирующими номерами

public long genRNG() 
{ 
    long mask = 0xFFFF000000000000L; 
    long randomValue = seed & mask; 
    seed = 0x5D588B656C078965L * cal.get(Calendar.MILLISECOND) + 0x0000000000269EC3; 
    return randomValue; 
} 

и вот мой основной метод

public static void main(String[] args) throws InterruptedException 
{ 
    Seed key = new Seed(); 
    for (int x = 0; x <=10; x++) 
    { 
     Thread.sleep(200); 
     System.out.println(key.genRNG()); 
    } 
} 

и данный выход:

-7389844038561562624 
-7389844038561562624 
-7389844038561562624 
-7389844038561562624 
-7389844038561562624 
-7389844038561562624 
-7389844038561562624 
-7389844038561562624 
-7389844038561562624 
+0

Вы изменяете значение переменной seed, возвращая 'randomValue'. – Andremoniy

+1

Что еще более важно, вы не меняете 'cal'. –

+0

randomValue состоит из Seed, хотя Andre –

ответ

1

Кажется, вы настраиваете mask с одинаковым значением каждый раз и seed с одинаковым значением каждый раз, поэтому seed & mask дает одинаковое значение каждый раз. Объект Calendar автоматически не изменяет свое значение после его создания - другими словами, он сохраняет время, которое было получено при его создании (обычно это время , когда было построено), пока вы явно не измените его. Таким образом, одно предложение - сделать повторно инициализацию cal в каждом звонке до genRNG().

Здесь я изменил cal локальной переменной:

long mask = 0xFFFF000000000000L; 
    long randomValue = seed & mask; 
    Calendar cal = Calendar.getInstance(); 
    seed = 0x5D588B656C078965L * cal.get(Calendar.MILLISECOND) + 0x0000000000269EC3; 
    return randomValue; 

Теперь я могу получить выход как:

0 
8430738502437568512 
-2453898846963499008 
2916080758722396160 
3291568377654411264 
-1326873040214032384 
-951385421282017280 
1212312724692795392 
-3406128693175648256 
-1298444067566256128 
-5916885485434699776 

Начальная 0 происходит от seed что не был инициализирован. Я понимаю, что это не проблема в вашем коде.

Я не думаю, что вы еще там. Calendar.get(Calendar.MILLISECOND) всегда возвращает значение в интервале от 0 до 999, поэтому вы получаете до 1000 различных «случайных» значений. Не много для хранения в long. Вы можете получить больше, например, так:

seed = 0x5D588B656C078965L * System.currentTimeMillis() + 0x0000000000269EC3; 

Если по какой-то причине вы хотите объект для текущего времени, а не только long вы получаете от System.currentTimeMillis(), если вы можете использовать Java 8, я предлагаю Instant.now().toEpochMilli() , Он дает вам то же значение long, но Instant.now() дает вам объект, представляющий текущее время, например, Calendar.getInstance(), только более современный и универсальный, если вы хотите использовать его для других целей.

Другая проблема связана с тем, что ваше значение всегда заканчивается 48 нулями в двоичном представлении (легко видеть, что все значения четные). Может быть, это так же конструировано?

Также, я полагаю, есть причина, по которой вы не просто используете java.util.Random.

+0

wow, это действительно хороший ответ! Большое вам спасибо, я бы поднял, но у меня недостаточно репутации. Я использовал Календарь, потому что я не знал о других методах отслеживания времени, и да, я пытаюсь сделать свою собственную версию линейного конгруэнтного генератор случайных чисел. –