Может кто-нибудь перенести это на Java? Как
эта работа, когда вы только подписали
номера доступны?
Нет стресса! a=18782
, поэтому наибольшее значение t
может быть недостаточно большим, чтобы вызвать проблемы со знаком и без знака. Вам придется «обновить» результат использования Q до значения, равного 32-битному числу без знака, прежде чем использовать его где-либо. например если Q - int
(32-разрядная подпись), то вам нужно будет сделать это, прежде чем использовать его в операторе t=a*Q[i]+c
, например,
t=a*(((long)Q[i])&0xffffffffL)+c
где этот бизнес (((long) Q [i]) & 0xffffffffL) переводит Q [i] в 64-битный # и гарантирует, что его старшие 32 бита равны 0. (edit: ПРИМЕЧАНИЕ: вам нужен 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());
}
}
};