随机发生器从C到Java的端口? [英] Port of Random generator from C to Java?

查看:95
本文介绍了随机发生器从C到Java的端口?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

乔治马尔萨利亚写了一个极好的随机数生成器,它是非常快,操作简单,而且具有更高的期比梅森倍捻机。这里是code有说明:

好的C的随机数发生器

我想端口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 largest t 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 an int (32-bit signed) then you'd have to do this before using it in the t=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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆