随机分布如discrete_distribution<float>

Random distribution like discrete_distribution<float>

discrete_distribution只能用于整数类型,浮点数有类似的东西吗?

我想写类似

的东西
distribution<float> myDistribution = {0.1, 0.2, 0.5, 0.2};

int index = myDistribution(generator);

重要的是随机数的生成是O(log(N))。

我宁愿找到使所有这些都是整数的公倍数并在 discrete_distribution 中使用它。

或者,如果确实需要,您可以使用 piecewise_constant_distribution。权重将是您的浮点数,然后间隔只是单位间隔。

std::vector<double> i{0.0,  1.0, 2.0, 3.0, 4.0};
std::vector<double> w{0.1, 0.2, 0.5, 0.2};

std::piecewise_constant_distribution<> d(i.begin(), i.end(), w.begin());

(然后通过flooring将结果转为int)

但是,我认为该标准不能保证任一生成器的复杂性。

std::discrete_distribution 的签名如下:

template< class IntType = int >
class discrete_distribution;

如解释:

IntType - The result type generated by the generator. The effect is undefined if this is not one of short, int, long, long long, unsigned short, unsigned int, unsigned long, or unsigned long long.

所以结果类型应该是整数。但是权重就不是这样了,可以是浮点数。实际上,constructor of this class 之一的签名是:

discrete_distribution( std::initializer_list<double> weights );

因此,我们可以使用浮点数作为权重:

#include <iostream>
#include <random>
#include <map>
#include <vector>

int main()
{
    std::random_device rd;
    std::mt19937 gen(rd());

    std::discrete_distribution<int> myDistribution = {0.1, 0.2, 0.5, 0.2};

    std::map<int, int> m;

    for(int n=0; n<10000; ++n) {
        ++m[myDistribution(gen)];
    }
    for(auto p : m) {
        std::cout << p.first << " generated " << p.second << " times\n";
    }

    return 0;
}

结果如下:

0 generated 1023 times
1 generated 1969 times
2 generated 5005 times
3 generated 2003 times

我们可以看到 std::initializer_list 中指示的权重得到了尊重。