【问题标题】:Linear Congruential Generator C线性同余生成器 C
【发布时间】:2014-06-30 16:20:04
【问题描述】:
  • 平台:Linux 3.2.0 x86 (Debian Wheezy)
  • 编译器:GCC 4.7.2 (Debian 4.7.2-5)

我正在编写一个线性同余生成器。我读过线性同余生成器生成的高阶位具有更高的周期。我想使用高阶位,但我不知道如何使用。我当前的实现使用了《数值食谱》一书中的“a”和“c”值,因为方程 ax+c 的最大可能值可以表示为 64 位整数。

#define ran32(seed) (uint32_t)((seed) * UINT64_C(1664525) + UINT64_C(1013904223))

我尝试了以下方法来消除低位,但据我所知,它不会返回无符号 32 位整数的整个范围内的值。

#define ran32(seed) (uint32_t)(((seed) * UINT64_C(1664525) + UINT64_C(1013904223)) / UINT64_C(256))

这个想法是用 2^8(256) 积分除以 'foo' >> 8。这个想法的灵感来自我在 rand() 的文档中找到的以下代码段。

static unsigned long next = 1;
int myrand(void)  /* RAND_MAX assumed to be 32767. */
{
    next = next * 1103515245 + 12345;
    return((unsigned)(next/65536) % 32768);
}

void mysrand(unsigned seed)
{
    next = seed;
}

【问题讨论】:

  • 我脑海中浮现的第一件事是……你到底为什么要那样做?
  • 这是一个问答网站,不是代码审查网站。
  • @BrandonYates 我已经更新了我的帖子,所以现在这是一个问题。
  • @Blindy 为了回答你的问题,我对线性同余生成器感兴趣。现在,如果您能回答我的问题,我将不胜感激。

标签: c


【解决方案1】:

一个问题可能是计算:

seed * 1664525 + 1013904223

生成一个 32 位值 (uint32_t),然后将其分配给一个 64 位变量。您可能希望将其作为 64 位计算。

但是,除非您经常溢出 64 位数字,否则您的最高有效字节不一定是非常随机的。

我认为您的代码也容易受到字节序问题的影响。

您对表达式最小值较大的分析忽略了 uint32_t 所包含的模数 232 算术。

【讨论】:

  • LCG 实际上是 (1664525 * Xₙ₋₁ + 1013904223) mod 2³²,来自 Numerical Recipes
  • @ninjalj:好的——这表明它应该是一个不错的 LCG PRNG。但是,我怀疑 Numerical Recipes 的代码与 64 位值混淆。
  • Numerical Recipesj = 1 + (int) (10.0 * (rand() / (RAND_MAX + 1.0)));,这也有问题。
  • @JonathanLeffler 我已经改变了我的问题,如果你能回答我的新问题,将不胜感激。
  • 我快速浏览了一下。如果你破解一个 PRNG,你几乎总是会得到一个更少的 PR 生成器,而不是你不理会它。阅读 Knuth “The Art of Computer Programming, Vol 2 Seminumerical Algorithms” 了解更多信息 - 比我有时间反刍的更多信息(假设我首先吸收了这些信息,这是值得商榷的)。在我看来,您需要一个 40 位 PRNG,然后您将从 32 位结果中删除最低有效 8 位。但是找到一个 40 位的 PRNG 可能很难;一个 64 位的可能更容易找到,并且可能对您同样有效。
猜你喜欢
  • 2015-08-22
  • 2013-10-09
  • 1970-01-01
  • 2016-07-03
  • 2012-08-19
  • 1970-01-01
  • 1970-01-01
  • 2019-11-29
  • 2013-07-11
相关资源
最近更新 更多