我希望生成可重复的随机数,代表三维空间中不同点的数量,例如:
double draw = rand(int seed, int x, int y, int z)
我希望相同的输入始终产生相同的结果。我不想提前生成所有值,因为数量太多。
我希望不同位置的抽样是独立的。我还希望对于不同种子的相同位置的抽样也是独立的。这排除了将四个参数的和或积作为种子的方法。
我希望生成可重复的随机数,代表三维空间中不同点的数量,例如:
double draw = rand(int seed, int x, int y, int z)
我希望相同的输入始终产生相同的结果。我不想提前生成所有值,因为数量太多。
我希望不同位置的抽样是独立的。我还希望对于不同种子的相同位置的抽样也是独立的。这排除了将四个参数的和或积作为种子的方法。
怎么样?
return new Random(seed ^ x ^ y ^ z).nextDouble();
(由于构造函数的种子参数实际上是64位,因此在异或之前将您的两个int向左移动32位,可以获得更好的“扩散”效果。)
另一个简单的解决方案是做类似于以下的事情
Random rnd = new Random(seed);
rnd.setSeed(rnd.nextLong() ^ x);
rnd.setSeed(rnd.nextLong() ^ y);
rnd.setSeed(rnd.nextLong() ^ z);
return rnd.nextDouble();
Random类使用一个48位的种子,方便地分成三个16位的部分,如下所示。
private static long createSeed(long x, long y, long z) {
return (z & 0xffff) << 32 + (yy & 0xffff) << 16 + (x & 0xffff);
}
Java有Random(long seed)构造函数,但它只接受一个长整型数值。
但你不必太担心,因为你可以将一个(数学)函数应用于你的向量和种子来产生一个单一的数字。一个简单的方法是将这些数字相加:
Random rand = new Random(seed+x+y+z);
但是,正如您自己可能已经注意到的那样,这并不是最好的方法,因为它对于(1,0,0)、(0,1,0)和(0,0,1)产生相同的结果。我相信您可以想出一个更好的函数,例如 seed + 31*31*x + 31*y + z
或类似函数。
setSeed()
API中所述,java.util.Random
使用48位种子。您的模型可能会建议定义一个适合哈希您的三个整数的函数。或者,您可以使用自定义实现扩展java.util.Random
。