我尝试使用给定日期生成随机数,以便在Java中创建良好的伪随机数。我决定使用Calendar
类并计算当天的毫秒数。这在一定程度上起作用,但是当我启动程序时,我只能获得不同的随机值。在程序中再运行它只会给我相同的数字。我使用Thread.sleep()
来确保时间上存在实际差异,但我仍然得到相同的数字。
这是我打电话的方法(来自另一个班级)
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 :(得分: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,我建议{ {1}}。它为您提供了相同的Instant.now().toEpochMilli()
值,但long
为您提供了一个表示当前时间的对象,与Instant.now()
非常相似,如果您想将其用于其他目的,则只会更现代,更通用
另一个问题是因为掩码,你的值总是以二进制表示的48个零结尾(很容易看到所有的值都是偶数)。也许这是设计的?
此外,我认为您不仅仅使用Calendar.getInstance()
。