基本上我想生成随机数,这些数字在很长一段时间内都不会重复(我不想使用序列),例如java使用的LCG:
synchronized protected int next(int bits) {
seed = (seed * 0x5DEECE66DL + 0xBL) & ((1L << 48) - 1);
return (int)(seed >>> (48 - bits));
}
据我所知,这种情况下的种子只会在2 ^ 48次调用后才重复,这是正确的吗?
所以我理解,如果我做了一个像:
这样的方法 synchronized protected long next() {
seed = (seed * 0x5DEECE66DL + 0xBL) & ((1L << 48) - 1);
return seed;
}
保证种子值在2 ^ 48次呼叫之前不重复?
答案 0 :(得分:8)
供参考,linear congruential generator中实施的java.util.Random
参数如下:
a = 25214903917 = 7 x 443 x 739 x 11003
c = 11
m = 2 48
a - 1 = 25214903916
当且仅当以下所有为真时,period length最多 m :
✔ c 和 m 并且是relatively prime
✔ a - 1可被 m 的所有素数因子整除
✔ a - 如果 m 是4的倍数,则1是4的倍数
是的,期限为2 48 。问题是“低阶位经历非常短的周期。”连续值的低阶位之间的强相关性显着限制了您可以用它们做什么。
答案 1 :(得分:4)
不适用于那个LCG,因为每次调用时你都会被2 ^ 48修改(因此周期/状态的长度最多为2 ^ 48)。如果你想要一个更好的随机数发生器,你可以尝试Mersenne twister:
http://en.wikipedia.org/wiki/Mersenne_twister
标准MT19937的周期为2 ^ 19937-1(!!!)这应该比您需要的更多。
答案 2 :(得分:1)
您可以使用SecureRandom代替随机替换。它的重复速度不如Random。
答案 3 :(得分:1)
您可以使用Collection.shuffle()
,因为这可能是性能问题..
ArrayList<Integer> number = new ArrayList<Integer>();
for (int i = 0; i < array.size(); ++i)
number.add(i);
Collections.shuffle(number);