如何使用std::generate_canonical在区间[0,1)中生成随机数?

5
我在使用 std::generate_canonical 时遇到了问题。根据我在cpp-reference.com上的阅读,我期望 std::generate_canonical 生成的数字范围为 [0,1)。然而,在最新的 MSVC 2012(未安装 CTP)上,std::generate_canonical 生成的数字都是 10^28 的数量级(见下文)。事实上,Microsoft 的文档中没有提到 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中。


我使用G++ 4.8在Linux中编译了这个程序,它生成了10个范围在[0,1)之间的随机数。我不知道微软对你做了什么。 - Joe Z
2
Visual Studio 2013也会生成虚假值。uniform_real_distribution可能适合你所需的。 - Retired Ninja
@RetiredNinja。实际上,现在使用uniform_real_distribution将是解决方案。 - Diederick C. Niehorster
3个回答

6

26.5.7.2 Function template generate_canonical [rand.util.canonical]

Each function instantiated from the template described in this section 26.5.7.2 maps the result of one or more invocations of a supplied uniform random number generator g to one member of the specified RealType such that, if the values gi produced by g are uniformly distributed, the instantiation's results tj, 0 ≤ tj < 1, are distributed as uniformly as possible as specified below.

template<class RealType, size_t bits, class URNG> 
RealType generate_canonical(URNG& g);
此外,标准规定此函数返回s/rk,其中
S
R
因此,此函数应返回从零到一的值。我认为,Microsoft在这里的实现是错误的。

1
感谢您报告在Microsoft Connect中的错误。 - Diederick C. Niehorster

1

你所提到的cpp reference目前显示:

"一些现有的实现存在一个错误,如果RealType是float,则它们偶尔可能返回1.0 GCC #63176 LLVM #18767。这是LWG问题2524"

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

该问题是在2015年8月20日开放的,比你发布这个问题的时间晚了几年。


-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());
}

2
这是原始问题中提供的链接。这并没有回答为什么MSVC++没有产生期望范围[0,1)内的值。 - Joe Z
5
好的,我看到您的编辑,其中包含一个详细的示例,但仍未解释为什么generate_canonical没有产生预期结果。您的示例甚至没有使用generate_canonical。您是否阅读了与我相同的问题? - Joe Z

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接