3 次元空間のさまざまな点の量を表す再現可能な乱数を生成したい。
double draw = rand(int seed, int x, int y, int z)
同じ入力で常に同じドローが生成されるようにします。値が多すぎるため、事前にすべての値を生成したくありません。
異なるポジションの抽選を独立させたい。また、シードが異なる同じポジションのドローを独立させたいと考えています。これにより、4 つの引数の合計または積を取り、これをシードとして使用することができなくなります。
3 次元空間のさまざまな点の量を表す再現可能な乱数を生成したい。
double draw = rand(int seed, int x, int y, int z)
同じ入力で常に同じドローが生成されるようにします。値が多すぎるため、事前にすべての値を生成したくありません。
異なるポジションの抽選を独立させたい。また、シードが異なる同じポジションのドローを独立させたいと考えています。これにより、4 つの引数の合計または積を取り、これをシードとして使用することができなくなります。
Randomクラスは、それぞれが 16 ビットの 3 つの部分に都合よく分割された 48 ビットのシードを使用します。
private static long createSeed(long x, long y, long z) {
return (z & 0xffff) << 32 + (yy & 0xffff) << 16 + (x & 0xffff);
}
どうですか
return new Random(seed ^ x ^ y ^ z).nextDouble();
(コンストラクターへのシード引数は実際には 64 ビットであるため、xor:ing の前に 2 つの 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();
JavaにはRandom(long seed)コンストラクターがありますが、必要なlong値は1つだけです。
ただし、(数学的な)関数をベクトルとシードに適用して単一の数値を生成できるため、それほど心配する必要はありません。貧乏人のバージョンは、単に数字を追加するだけです。
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ビットシードを使用します。モデルは、3つの整数をハッシュするための適切な関数の定義を提案する場合があります。java.util.Random
または、カスタム実装で拡張することもできます。