我需要一个PRNG来进行模拟项目,然后发现a resource,因为我对PRNG的了解有限但并非根本不存在,因此听起来似乎很明智。我试图将本报告中给出的算法封装在一个类中,但是由于某种原因,我得到了很多重复的值。 PRNG可能不如报告中说明的那样好,但是我怀疑这是我的实现失败的原因。
背景:报告中的PRNG代码
第3页上给出以下代码示例:
/* Public domain code for JKISS RNG */
// seed variables
static unsigned int x = 123456789,y = 987654321,z = 43219876,c = 6543217;
unsigned int JKISS()
{
unsigned long long t;
x = 314527869 * x + 1234567;
y ^= y << 5; y ^= y >> 7; y ^= y << 22;
t = 4294584393ULL * z + c; c = t >> 32; z = t;
return x + y + z;
}
关于这一点,报告声称
JKISS的周期为≈2127 = 1.7x10 38(2 32 x(2 32 -1)x(1/2 *
4294584393 x 2 32-1)),它通过了所有的Dieharder测试和完整的BigCrunch测试集
TestU01。
所以这对我来说绝对足够好。在报告的后面(第6页)中对此进行了说明
以下C代码生成[sic]随机(双精度)浮点数0
double x;
x = JKISS() / 4294967296.0;
我对此的封装
我在头文件中有以下内容:
class JKISS : public IPRNG {
private:
// Seed variables
static unsigned int x;
static unsigned int y;
static unsigned int z;
static unsigned int c;
public:
static unsigned int randui32();
static double randdouble();
};
与以下实现文件
#include "prng.hpp"
unsigned int JKISS::x = 123456789;
unsigned int JKISS::y = 987654321;
unsigned int JKISS::z = 43219876;
unsigned int JKISS::c = 6543217;
unsigned int JKISS::randui32() {
unsigned long long t;
x = 314527869 * x + 1234567;
y ^= y << 5; y ^= y >> 7; y ^= y << 22;
t = 4294584393ULL * z + c; c = t >> 32; z = t;
return x + y + z;
}
double JKISS::randdouble() {
return randui32() / 4294967296.0;
}
和下面的主程序
#include <iostream>
#include "prng.hpp"
int main() {
for (int i = 0; i < 10000; ++i) {
std::cout << JKISS::randdouble() << std::endl;
}
}
如您所见,我已经复制粘贴了大部分代码。
但是,当我运行此代码时,即使我仅获取10000个值,也得到68个重复值。这向我表明我的封装有问题,但我无法弄清楚问题出在哪里。
万一有问题,我将在Ubuntu 13.10上以以下规格运行GCC 4.8.1:
Platform Info:
System: Linux (x86_64-linux-gnu)
CPU: Intel(R) Xeon(R) CPU E5410 @ 2.33GHz
WORD_SIZE: 64
任何可能导致这种情况的想法都将受到欢迎。
最佳答案
我得到的结果与您相同,但没有重复; p
我的意思是,如果我按照指示运行程序,则会得到68个重复项,但是如果我切换randdouble()
=> randui32()
,将不再有重复项,因此我敢打赌,由于打印例程。
您可以尝试将双打收集到一个数组中,然后进行比较以确保100%确定。