【问题标题】:How can I transform a random integer to a uniform real [0,1[ distribution如何将随机整数转换为统一的实数 [0,1[ 分布
【发布时间】:2014-07-16 00:33:24
【问题描述】:

在维基百科上,我发现了以下random number generator

#include <stdint.h>

/* The state must be seeded so that it is not everywhere zero. */

uint64_t s[ 2 ];

uint64_t next(void) { 
    uint64_t s1 = s[ 0 ];
    const uint64_t s0 = s[ 1 ];
    s[ 0 ] = s0;
    s1 ^= s1 << 23;
    return ( s[ 1 ] = ( s1 ^ s0 ^ ( s1 >> 17 ) ^ ( s0 >> 26 ) ) ) + s0;
}

现在,当实施时(使用 s[0] 和 s1 的随机种子),这很好用,但输出的数字如下:

2318509732609079156, 5455176535758408500, 14446583927462861784, 3420274542024626201, etc.

我现在的问题是:如何将这些数字转换为均匀的实数分布 [0,1[,即包括 0 和排除 1?

【问题讨论】:

  • 只需将整数随机数除以2.0^​​64
  • 在 C++11 中有一个完整的库:<random>。你自己有这样做的理由吗?
  • 我推荐这个关于 C++11 中随机生成器的讨论:channel9.msdn.com/Events/GoingNative/2013/…;获得正确的随机数很难。
  • 是的@DmitryLedentsov,速度。我特别选择了这个算法,因为它被认为是最快的随机数引擎之一。我正在编写一个程序,其主要速度瓶颈是随机数生成,因此与 Mersenne Twister 或 Lagged Fibonnaci 生成器一样快,它们仍然比这个慢。
  • @PeterG。非常感谢,这似乎已经成功了! (至少,乍一看)。但请问:你怎么知道这是除数?

标签: c++ random distribution


【解决方案1】:

假设您想要 double 结果,只需将随机生成器的结果转换为 double 并除以最大值(即 2^64):

double result = next() / (double) std::numeric_limits<uint64_t>::max();

请注意,转换为 64 位实数值时可能会丢失一些精度,因此这些值可能不会完全均匀分布。如果这对您的应用程序很重要,则不应使用此代码...

编辑:抱歉,这也可能导致值1。一个简单的解决方法是重复此操作,直到值不是 1,或者确保 next() 永远不会返回 std::numeric_limits&lt;uint64_t&gt;::max()

编辑:更简单,受 40two 的回答启发:使用随机生成器调用 std::uniform_real_distribution:

std::uniform_real_distribution<double> distribution(0.0,1.0);
double random_number_in_01 = distribution(next);

【讨论】:

  • 您的原始答案具有误导性。如果以双精度除以 2^64-1,则会得到非均匀分布的数字,因为浮点数在所有间隔中都没有均匀的密度。欲了解更多信息:crypto.stackexchange.com/questions/31657/…
【解决方案2】:

在 C++11 中,有一种方法可以在 std::uniform_real_distribution 的区间内生成均匀分布的数字:

// uniform_real_distribution
#include <iostream>
#include <random>

int main()
{
  std::default_random_engine generator;
  std::uniform_real_distribution<double> distribution(0.0,1.0);
  double random_number_in_01 = distribution(generator);

  return 0;
} 

【讨论】:

  • 非常感谢您的评论!我非常了解标准库的随机数生成器,但就我而言,速度是最重要的。标准库中的生成器速度很快,但我将它们与这个简单的算法进行了比较,它们的速度要慢得多。
  • 关于 C++11 随机数模型,您的算法是 random_engine。也许您应该尝试通过将您的算法转换为自定义 random_engine 来融入 C++11 随机数,然后您可以将其与 std::uniform_real_distribution 一起使用。
猜你喜欢
  • 2016-10-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-09
相关资源
最近更新 更多