题
乔治Marsaglia写了一个极好的随机数发生器,是非常快速、简便和具有更高的期限比梅森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?这怎么工作,当你只有数字签名吗?
编辑: 谢谢大家快速的答案!第一个100万这个数字代码似乎产生相同的结果C码。这是3倍的速度比Java的java。工具.随机的。
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;
}
}
解决方案
任何人都可以这个端口到Java?如何 这项工作时,你只签署 可供选择的数字?
没有压力! a=18782
所以最大t
可能永远不会是没有大到足以引起对签订无符号的问题。你将不得不“升级”用品质在任何地方使用它之前等于32位无符号数的值的结果。例如如果Q是int
(32位有符号),那么你就必须在t=a*Q[i]+c
声明中,例如在使用它之前做到这一点
t=a*(((long)Q[i])&0xffffffffL)+c
其中这个(((长)Q [I])&0xffffffffL)业务促进Q [I]到64比特#,并确保其高32个比特是0。 (编辑:注意:您需要0xffffffffL这里的Java做了错误的事情,如果你使用的0xffffffff,这似乎是为“优化”自己的错误的答案和你得到一个负数,如果Q [I]的最高位为1。 )
您应该能够通过运行在C算法++和Java到输出比较验证这一点。
编辑:这里有一个镜头吧。我试图在C ++和Java对于N = 100000运行它;它们都匹配。如果我用坏的Java成语道歉,我还是相当新的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:(慢于编译的C ++,但它对于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());
}
}
};
其他提示
大多数时候也没有必要使用更大的数值类型在Java模拟无符号类型。
有关的加,减,乘,左移,逻辑操作,平等 并浇铸到一个较小的数值类型 不要紧操作数是否有符号或无符号, 结果将是相同的,无论,看作是一个位模式。
有关右移>>使用有符号,>>>为无符号的。
有关签订强制转换为更大的类型就去做。
有关无符号铸件从较小型的长期使用与型长为较小型的掩模。 例如,短到长:S&0xffffL
有关从较小的类型为int使用&与int类型的掩模无符号铸造。 例如,字节到int:B&0xff的
否则不喜欢在INT壳体和在顶部施加的铸造。 例如,字节到短:(短)(B&0xff的)
有关的比较运算符<等等和分裂的最简单的是投射到一个更大的类型,并执行操作那里。 但是,也存在其他选项,例如加入适当的偏移量后做比较。
如果你正在实施一个丽贝卡在爪哇,这是最佳的子类的 java。工具.随机的 类和复盖受保护的 下一个(int) 方法(你丽贝卡是那么一个简易替换为java。工具.随机).下一个(int)的方法感到关切的是随机产生的位,而不是瓦莱斯这位可能表示。其他的(公共)方法。工具.随意使用这些位建随机的价值观的不同种类型。
要绕过Java的缺乏,你通常存储在一个更大的变量类型的数字签名类型(所以短裤获得升级到整数,整数长)。既然你在这里使用长变量,你将不得不加紧BigInteger的,这可能会破坏你得到了算法的任何速度上涨。
只是作为一个快速的参考点可能(或可能不会)帮你,我发现此链接:
你可以使用数字签名所提供的价值不溢出...例如长在java是64位整数。然而意图在这个算法似乎是利用一64位unsigned值,和如果是这样我认为你会走运的基本类型。
你可以使用的multiprecision,针整数设在java类库(BigInteger).或者你可以实现自己的64位未签署的类型作为一种对象包含两个java渴望表示最显着和最重要的词(但你会拥有实施基本的算术运算自己在类)。