如何使用std :: generate_canonical生成范围[0,1)中的随机数?

时间:2013-12-15 06:12:20

标签: c++ visual-c++ c++11

尝试使用std::generate_canonical时遇到问题。根据我在cpp-reference.com的阅读,我希望std::generate_canonical能够生成[0,1]范围内的数字。 但是,在最新的MSVC 2012(未安装CTP)上,std::generate_canonical生成的数字全部为10 ^ 28(见下文)。实际上,Microsoft's documentation未提及std::generate_canonical生成数字的范围。

Microsoft是否不符合此处的标准?或者是标准缺陷,因为它对std::generate_canonical的行为含糊不清?在第二种情况下,如何编写代码以生成[0,1)范围内的随机浮点数?

请考虑以下示例代码,以便我尝试使用std::generate_canonical

#include <random>
#include <limits>
#include <iostream>

int main(int argc, char* argv[])
{
    std::random_device rd;
    // seed with true source of randomness
    std::mt19937 _rng_generator(rd());

    for(int n=0; n<10; ++n)
        std::cout << std::generate_canonical<double,std::numeric_limits<double>::digits>(_rng_generator) << ' ';

    return EXIT_SUCCESS;
}

我得到的输出示例:
    4.85267e+028 2.76741e+028 3.17392e+028 5.84136e+028 1.0037e+028 4.87202e+028 2.53834e+028 4.233e+028 6.43922e+028 2.30694e+028

更新 我之前向Microsoft Connect报告了这个错误。该错误现已修复,修复程序将包含在MSVC 2014 RTM中。

3 个答案:

答案 0 :(得分:6)

  

26.5.7.2函数模板generate_canonical [rand.util.canonical]

     

每个函数都是从本节中描述的模板中实例化的   26.5.7.2将提供的统一随机数生成器g的一个或多个调用的结果映射到指定的一个成员   RealType,如果g生成的值g i 是统一的   分布式,实例化的结果tj,0≤tj&lt; 1,是   按照以下规定尽可能均匀地分发。

template<class RealType, size_t bits, class URNG> 
RealType generate_canonical(URNG& g);

此外,标准描述,此函数返回s/rk,其中
S
R

因此,此函数应返回从0到1的值。我认为,微软的实施在这里是错误的。

答案 1 :(得分:0)

您当前所指的cpp reference说:

“某些现有实现存在一个错误,如果RealType为float GCC,则偶尔会返回1.0 GCC#63176 LLVM#18767。这是LWG问题2524”

根据issue,“问题在于该标准指定了实现,而该实现不起作用。”

此问题于您发布此问题几年后的2015年8月20日开放。

答案 2 :(得分:-4)

以下是MSDN文档:

http://msdn.microsoft.com/en-us/library/ee462289.aspx

这是相应的原型:

template<class RealType,
    size_t bits,
    class Engine>
    RealType generate_canonical(Engine& gen);

这是一个完整的例子:

http://msdn.microsoft.com/en-us/library/bb982398.aspx

// cl.exe /EHsc /nologo /W4 /MTd
#include <algorithm>
#include <array>
#include <iostream>
#include <ostream>
#include <random>
#include <string>
#include <vector>
using namespace std;

template <typename C> void print(const C& c) {
    for (const auto& e : c) {
        cout << e << " ";
    }

    cout << endl;
}

void test(unsigned int seed) {
    cout << "Seed: " << seed << endl;

    mt19937 engine(seed);

    uniform_int_distribution<int> dist(-3, 5);

    vector<int> v;

    for (int i = 0; i < 30; ++i) {
        v.push_back(dist(engine));
    }

    cout << "Randomized vector: ";
    print(v);

    array<string, 26> arr = { { "H", "He", "Li", "Be", "B", "C", "N", "O", "F",
        "Ne", "Na", "Mg", "Al", "Si", "P", "S", "Cl", "Ar", "K", "Ca", "Sc",
        "Ti", "V", "Cr", "Mn", "Fe" } };

    shuffle(arr.begin(), arr.end(), engine);

    cout << "Randomized array: ";
    print(arr);
}

int main() {
    cout << "--" << endl;

    test(12345);

    cout << "--" << endl;

    random_device rd;

    test(rd());
}