随机发生器从C到Java的端口? [英] Port of Random generator from C to Java?
问题描述
乔治马尔萨利亚写了一个极好的随机数生成器,它是非常快,操作简单,而且具有更高的期比梅森倍捻机。这里是code有说明:
我想端口CMWC4096 code到Java,但是它使用几个无符号的数据类型,所以我不知道如何正确地做到这一点。下面是完整的C code:
/ *选择随机初始℃下809430660和* /
/ * 4096随机32位整数Q [] * /
静态无符号长Q [4096],C = 362436;无符号长CMWC4096(无效){
无符号长长的T,A = 18782LL;
静态无符号长I = 4095;
无符号长X,R = 0xfffffffe;
I =(I + 1)及4095;
T = A * Q [I] +℃;
C =(T>> 32);
X = T + C;
如果(X c为C){
X ++;
C ++;
}
收益率(Q [I] = R - X);
}
任何人都可以这个端口到Java?这是如何工作时,你只签订了编号可用?
编辑:谢谢大家的快速解答!对于第一个100万个号码这个Java code似乎产生相同的结果C $ C $℃。它比Java的java.util.Random中快3倍。
公共类ComplimentaryMultiplyWithCarryRandom { / **
*选择4096随机32位整数
* /
私人长期[]问; / **
*选择随机初始℃下809430660
* /
私人长期C = 362436; 私人诠释我; 公共ComplimentaryMultiplyWithCarryRandom(){
随机R =新的随机(1);
Q =新长[4096]; // TODO初始化真正随机32位值
的for(int i = 0; I< 4096; ++ I){
长V = r.nextInt();
v - 输出= Integer.MIN_VALUE的;
Q [I] = V;
}
I = 4095;
} 接下来INT(){
I =(I + 1)及4095;
长T = 18782 * Q [I] +℃;
C = T>>> 32;
长×=(T + C)及0xffffffffL;
如果(X c为C){
+ X;
++℃;
} 长V = 0xfffffffeL - X;
Q [I] = V;
回报(INT)V;
}
}
任何人都可以这个端口到Java?如何
这项工作时,你只签署
可供选择的数字?
块引用>没有压力!
A = 18782
所以最大的T
可能永远不会是没有大到足以引起对签订无符号的问题。你将不得不升级用Q以在任何地方使用它之前,相当于一个32位无符号数的值的结果。例如如果Q是INT
(32位有符号),那么你就必须在T = A * Q使用它[之前做到这一点我] + c可
语句,如:T = A *(((长)Q [I])及0xffffffffL)+ C
这哪里(((长)Q [I])及0xffffffffL)的业务宣传Q [我]对64位#,并确保其高32位为0。 (编辑:注意:您需要0xffffffffL这里的Java做了错误的事情,如果你使用为0xffffffff,这似乎是为优化自己错误的答案和放大器;你得到一个负数,如果Q [I]的最高位为1。 。)
您应该能够运行在C ++算法和Java到输出比较验证这一点。
编辑:这里有一个镜头吧。我试着在C ++和Java为N = 100000运行它;他们都匹配。如果我用坏的Java成语道歉,我还是相当新的Java的。
C ++
// marsaglia2003.cpp#包括LT&;&stdio.h中GT;
#包括LT&;&stdlib.h中GT; //为的atoiM2003类
{
枚举{C0 = 362436,SZ = 4096,面膜= 4095};
无符号长Q [深圳]
无符号长℃;
总之我;上市:
M2003()
{
//真正的程序具有良好的随机种子种子本
//我只是投入的东西,使输出有趣
对于(INT J = 0; J< SZ ++ j)条
Q [J] = J +(J<< 16);
I = 4095;
C = C0;
} 无符号长的next()
{
无符号长长的T,A = 18782LL;
无符号长×;
无符号长R = 0xfffffffe;
I =(I + 1)及掩模;
T = A * Q [I] +℃;
C =(无符号长)(T>> 32);
X =(无符号长)T + C;
如果(X c为C)
{
X ++;
C ++;
}
收益率(Q [I] = R-X);
}
};INT主(INT ARGC,CHAR *的argv [])
{
M2003发生器;
INT N = 100;
如果(argc个大于1)
N =的atoi(ARGV [1]); 的for(int i = 0; I< N ++ I)
{
的printf(%08X \\ n,generator.next());
}
返回0;
}Java的:(慢编译的C ++,但对于N = 100000匹配)
// Marsaglia2003.java进口的java.util。*;类Marsaglia2003
{
最终静态私人INT SZ = 4096;
最终静态私人INT面膜= 4095;
最终私人诠释[] Q =新INT [深圳]
私人INT C = 362436;
私人INT I = SZ-1; 公共Marsaglia2003()
{
//真正的程序具有良好的随机种子种子本
//我只是投入的东西,使输出有趣
对于(INT J = 0; J< SZ ++ j)条
Q [J] = J +(J<< 16);
} 接下来公众诠释()
//注:返回一个符号的32位数字。
//如果你想使用未签名的,转换为(长)
//然后,它使用0xffffffffL
{
长T,A = 18782;
INT X;
INT R = 0xfffffffe;
I =(I + 1)及掩模;
长齐=((长)Q [I])及0xffffffffL; //视为32位无符号
T = A *奇+ C;
C =(INT)(T>> 32);
//因为a是比较小的这个成绩也小 X =((INT)T)+ C;
如果(X< C&放大器;&安培; X> = 0)//调整,以把X作为无符号
{
X ++;
C ++;
}
收益率(Q [I] = R-X);
} 公共静态无效的主要(字符串ARGS [])
{
Marsaglia2003 M2003 =新Marsaglia2003(); INT N = 100;
如果(args.length大于0)
N =的Integer.parseInt(参数[0]);
的for(int i = 0; I< N ++ I)
{
System.out.printf(%08X \\ n,m2003.next());
}
}
};George Marsaglia has written an excellent random number generator that is extremely fast, simple, and has a much higher period than the Mersenne Twister. Here is the code with a description:
good C random number generator
I wanted to port the CMWC4096 code to Java, but it uses several unsigned datatypes so I am not sure how to do this properly. Here is the full C code:
/* 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); }
Can anyone port this to Java? How does this work when you only have signed numbers available?
EDIT: Thanks everybody for the quick answers! For the first 100 million numbers this java code seems to produce the same result as the C code. It is 3 times faster than Java's java.util.Random.
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; } }
解决方案Can anyone port this to Java? How does this work when you only have signed numbers available?
No Stress!
a=18782
so the largestt
could ever be is not large enough to cause signed vs. unsigned problems. You would have to "upgrade" the result of using Q to a value equal to a 32-bit unsigned number before using it anywhere. e.g. if Q is anint
(32-bit signed) then you'd have to do this before using it in thet=a*Q[i]+c
statement, e.g.t=a*(((long)Q[i])&0xffffffffL)+c
where this (((long)Q[i])&0xffffffffL) business promotes Q[i] to a 64-bit # and ensures its high 32 bits are 0's. (edit: NOTE: you need 0xffffffffL here. Java does the wrong thing if you use 0xffffffff, it seems like it "optimizes" itself to the wrong answer & you get a negative number if Q[i]'s high bit is 1.)
You should be able to verify this by running the algorithms in C++ and Java to compare the outputs.
edit: here's a shot at it. I tried running it in C++ and Java for N=100000; they both match. Apologies if I used bad Java idioms, I'm still fairly new to Java.
C++:
// marsaglia2003.cpp #include <stdio.h> #include <stdlib.h> // for atoi class m2003 { enum {c0=362436, sz=4096, mask=4095}; unsigned long Q[sz]; unsigned long c; short i; public: m2003() { // a real program would seed this with a good random seed // i'm just putting in something that makes the output interesting for (int j = 0; j < sz; ++j) Q[j] = j + (j << 16); i = 4095; c = c0; } unsigned long next() { unsigned long long t, a=18782LL; unsigned long x; unsigned long r=0xfffffffe; i = (i+1)&mask; t=a*Q[i]+c; c=(unsigned long)(t>>32); x=(unsigned long)t + c; if (x<c) { x++; c++; } return (Q[i]=r-x); } }; int main(int argc, char *argv[]) { m2003 generator; int n = 100; if (argc > 1) n = atoi(argv[1]); for (int i = 0; i < n; ++i) { printf("%08x\n", generator.next()); } return 0; }
java: (slower than compiled C++ but it matches for N=100000)
// Marsaglia2003.java import java.util.*; class Marsaglia2003 { final static private int sz=4096; final static private int mask=4095; final private int[] Q = new int[sz]; private int c=362436; private int i=sz-1; public Marsaglia2003() { // a real program would seed this with a good random seed // i'm just putting in something that makes the output interesting for (int j = 0; j < sz; ++j) Q[j] = j + (j << 16); } public int next() // note: returns a SIGNED 32-bit number. // if you want to use as unsigned, cast to a (long), // then AND it with 0xffffffffL { long t, a=18782; int x; int r=0xfffffffe; i = (i+1)&mask; long Qi = ((long)Q[i]) & 0xffffffffL; // treat as unsigned 32-bit t=a*Qi+c; c=(int)(t>>32); // because "a" is relatively small this result is also small x=((int)t) + c; if (x<c && x>=0) // tweak to treat x as unsigned { x++; c++; } return (Q[i]=r-x); } public static void main(String args[]) { Marsaglia2003 m2003 = new Marsaglia2003(); int n = 100; if (args.length > 0) n = Integer.parseInt(args[0]); for (int i = 0; i < n; ++i) { System.out.printf("%08x\n", m2003.next()); } } };
这篇关于随机发生器从C到Java的端口?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!