【问题标题】:Are there any linear congruential generator algorithms that return only positive values?是否有任何只返回正值的线性同余生成器算法?
【发布时间】:2013-12-26 23:26:19
【问题描述】:

我知道一个; ZX Spectrum apparently 使用模数为 65537 和乘数为 75 的 Lehmer RNG。这只会生成大于零的数字。但是,我想使用周期超过 2^16 - 1 的东西。

我在整数(Haxe)的 32 位字长的语言中使用它,所以理想情况下它会小于 2^31。但是,我不一定要寻找特定于 Haxe 的答案。

【问题讨论】:

  • 否定只是解释...
  • 恐怕看不懂,要详细说明吗?我正在寻找从函数返回一个正整数。我尝试了显而易见的方法,但使用 Math.abs() 大大减慢了速度。
  • 你看过这个页面吗? en.wikipedia.org/wiki/Linear_congruential_generator您通过在输出中不包含符号位来生成正值。
  • 使用 Math.Abs​​() 大大减慢了速度?这似乎不对……if (result < 0) return -1 * result; 怎么样?
  • 或者你可以将结果与 0x7FFFFFF 相加。这将清除任何负面结果的高位。即return result & 0x7FFFFFF;

标签: algorithm integer prng


【解决方案1】:

在使用二进制补码的机器中(这意味着 x86 和衍生产品,以及您可能遇到的几乎任何其他计算机),高位用于指示符号。如果设置了高位,则为负数。

所以你可以通过清除高位来确保一个数字是正数。对于 32 位数字,这是一个简单的问题:

result = result & 0x7FFFFFFF;

【讨论】:

    【解决方案2】:

    好的,这应该很明显,但我想通了。这是我的方程式:

    internalSeed = ( internalSeed * MULTIPLIER + INCREMENT ) % MODULUS + MODULUS;

    为了防止超出整数的字长,同时仍然提供大量返回,我使用了 Microsoft Visual Basic 6 伪随机值:

    MULTIPLIER = 1140671485
    INCREMENT = 12820163
    MODULUS = 16777216
    

    然后+ MODULUS 值当然会将范围从 (-16777216, 16777216) 更改为 (0, 33554429),这正是我想要的。

    编辑:上面的一些 cmets 提供了不同的解决方案。

    代替Math.abs(),总是可以对if ( result < 0 ) 进行简单检查,如果为真,则将结果乘以-1。我不确定这会对速度产生多大影响,但我认为不会有太大影响。

    最复杂的答案是您使用 0x7FFFFFFF 对结果进行按位与运算,以修剪负位。这对速度没有影响,并且确实确保了正值。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-08-22
      • 2013-10-09
      • 1970-01-01
      • 2010-12-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多