George Marsaglia は、Mersenne Twister よりもはるかに高速で単純な周期を持つ優れた乱数ジェネレータを作成しました。説明付きのコードは次のとおりです。
CMWC4096 コードを Java に移植したかったのですが、いくつかの署名されていないデータ型を使用しているため、これを適切に行う方法がわかりません。完全な C コードは次のとおりです。
/* choose random initial c<809430660 and */
/* 4096 random 32-bit integers for Q[] */
static unsigned long Q[4096],c=362436;
unsigned long CMWC4096(void) {
unsigned long long t, a=18782LL;
static unsigned long i=4095;
unsigned long x,r=0xfffffffe;
i = (i+1) & 4095;
t = a*Q[i] + c;
c = (t>>32);
x = t + c;
if (x < c) {
x++;
c++;
}
return (Q[i] = r - x);
}
誰でもこれを Java に移植できますか? 署名された番号しか利用できない場合、これはどのように機能しますか?
編集:迅速な回答をありがとうございました!最初の 1 億の数値では、この Java コードは C コードと同じ結果を生成するようです。Java の java.util.Random よりも 3 倍高速です。
public class ComplimentaryMultiplyWithCarryRandom {
/**
* Choose 4096 random 32-bit integers
*/
private long[] Q;
/**
* choose random initial c<809430660
*/
private long c = 362436;
private int i;
public ComplimentaryMultiplyWithCarryRandom() {
Random r = new Random(1);
Q = new long[4096];
// TODO initialize with real random 32bit values
for (int i = 0; i < 4096; ++i) {
long v = r.nextInt();
v -= Integer.MIN_VALUE;
Q[i] = v;
}
i = 4095;
}
int next() {
i = (i + 1) & 4095;
long t = 18782 * Q[i] + c;
c = t >>> 32;
long x = (t + c) & 0xffffffffL;
if (x < c) {
++x;
++c;
}
long v = 0xfffffffeL - x;
Q[i] = v;
return (int) v;
}
}