【问题标题】:What are the advantages of using uniform_int_distribution vs a modulus operation?使用 uniform_int_distribution 与模数运算有什么优势?
【发布时间】:2015-12-27 22:02:23
【问题描述】:

根据以下结果,使用%操作在两个数字之间生成均匀随机整数几乎比使用std::uniform_int_distribution快3倍:有什么好的理由使用std::uniform_int_distribution吗?

代码:

#include <iostream>
#include <functional>
#include <vector>
#include <algorithm>
#include <random>

#include <cstdio>
#include <cstdlib>

using namespace std;

#define N 100000000

int main()
{

clock_t tic,toc;

for(int trials=0; trials<3; trials++)
{
    cout<<"trial: "<<trials<<endl;

    // uniform_int_distribution
    {
        int res = 0;
        mt19937 gen(1);
        uniform_int_distribution<int> dist(0,999);

        tic = clock();
        for(int i=0; i<N; i++)
        {
            int r = dist(gen);
            res += r;
            res %= 1000;
        }
        toc = clock();
        cout << "uniform_int_distribution: "<<(float)(toc-tic)/CLOCKS_PER_SEC << endl;
        cout<<res<<" "<<endl;

    }

    // simple modulus operation
    {
        int res = 0;
        mt19937 gen(1);

        tic = clock();
        for(int i=0; i<N; i++)
        {
            int r = gen()%1000;
            res += r;
            res %= 1000;
        }
        toc = clock();
        cout << "simple modulus operation: "<<(float)(toc-tic)/CLOCKS_PER_SEC << endl;
        cout<<res<<" "<<endl;

    }

    cout<<endl;
}

}

输出:

trial: 0
uniform_int_distribution: 2.90289
538 
simple modulus operation: 1.0232
575 

trial: 1
uniform_int_distribution: 2.86416
538 
simple modulus operation: 1.01866
575 

trial: 2
uniform_int_distribution: 2.94309
538 
simple modulus operation: 1.01809
575 

【问题讨论】:

  • std::uniform_int_distribution 能够在任何整数区间之间生成均匀分布,而% 则不能。
  • 如果你不需要做对的话,写出快速的代码是很容易的。
  • 旁白:我会尝试不使用res %= 1000; 行。我可以想象有几种方法会搞砸你的测试。
  • 也许是因为它是制服

标签: c++ c++11 random stl


【解决方案1】:

当您使用模 (%) 来映射例如rand() 到另一个间隔。

例如,假设 rand() 统一(无偏差)映射到 [0, 32767],并且您想映射到 [0,4] 执行 rand() % 5。那么值 0、1 和 2 将平均产生 32768 次中的 6554 次,但值 3 和 4 仅产生 6553 次(因此 3 * 6554 + 2 * 6553 = 32768)。

偏差很小 (0.01%),但取决于您的应用程序,这可能是致命的。观看 Stephan T. Lavavej 的演讲“rand() considered harmful”了解更多详情。

【讨论】:

  • 公平地说,一个推论是如果模数是 2 的常数幂,那么 % rsp。 &amp; 可能比uniform_int_distribution 快得多,并且在通常的实现上没有引入任何偏差。
  • @ArneVogel true,但前提是 RAND_MAX 也是 2 的幂。此值取决于实现。保证此值至少为 32767。对于可移植代码和通用接口,只需使用uniform_int_distribution
  • @ArneVogel 这看起来像是 QOI 问题,不是吗?但是,如果您有一个具有 X 位熵的随机数,它是 Y 位宽且熵均匀分布,如果您提取较低的 Z 位,您最终会得到 X * Z/Y 位熵。如果您改为将所有 Y 位放入结果中(一个简单的移位异或系统),您的输出仍然可以有多达 X 位的熵(假设 X
  • @Yakk 如果您的随机数生成器返回 M 个数字之一,100% 随机返回,并且您需要 N 个数字之一,那么除非 M 可被 N any 操作整除接受M个原始数字中的每个并将其映射到N个数字中的一个将是有偏差的。您需要计算 M',它是 N 的倍数,将这些 M' 中的任何一个数字映射到 N 个数字中的一个,如果选择了另一个数字,则拒绝它并选择另一个(或使用更复杂的方法)。跨度>
  • @gnasher729 如果你在晴朗的中午没有云层的时候走到外面,天空是蓝色的。天空不可能是带有绿色条纹的淡粉色。 (简而言之,你在说什么?你的语法看起来像是在回应我的评论,但你充其量只是在谈论一些与我正在谈论的内容无关的事情,并且这样做好像你不同意我的观点?我正在解决 ArneVogel 的暗示立场,即如果源随机数据范围和模数都是 2 的幂,% 可能是一个好主意。这就是 @arnevogel 的意思。看看 Arne 的评论)
猜你喜欢
  • 1970-01-01
  • 2014-12-05
  • 2010-09-24
  • 2010-12-27
  • 2015-04-06
  • 2013-05-09
  • 2011-08-03
  • 2017-05-29
相关资源
最近更新 更多