C++ 为什么没有统一的分布?

C++ 为什么没有统一的分布?,c++,C++,我们有uniform\u int\u分布和uniform\u real\u分布,难道不可能有一个全面的uniform\u分布,专门处理浮点/双精度和int/…,如果指定的话 AFAIU,@user877329和@revolver\u ocelot的上述评论正确地解释了这一点,而另一个答案则完全错误 统一uniform\u int和uniform\u real的接口是错误的,这不是因为它们的实现方式不同(可以通过模板专门化来解决),而是因为接口的含义不同 假设我们统一接口(使用另一个答案中建议的变

我们有
uniform\u int\u分布
uniform\u real\u分布
,难道不可能有一个全面的
uniform\u分布
,专门处理浮点/双精度和int/…,如果指定的话

AFAIU,@user877329和@revolver\u ocelot的上述评论正确地解释了这一点,而另一个答案则完全错误

统一
uniform\u int
uniform\u real
的接口是错误的,这不是因为它们的实现方式不同(可以通过模板专门化来解决),而是因为接口的含义不同

假设我们统一接口(使用另一个答案中建议的变体),如下所示:

template <typename T>
using uniform_distribution =
    typename std::conditional<
        std::is_integral<T>::value,
        std::uniform_int_distribution<T>,
        std::uniform_real_distribution<T>
    >::type;
此代码说明使用此类编写泛型代码是危险的。例如,如果编写一个通用函数来计算子范围[0,1]、[1,2]、[8,9]中结果的直方图,则结果将不兼容



正如@revolver\u ocelot所指出的,标准库不能用于统一整数(因为不可能指定一个统一整数随机数生成器来生成最大uint值)有一种想法:uniform\u int\u分布使用闭合区间,uniform\u real\u分布使用半开区间。您不能定义自己的结构并对其进行专门化吗?它确实很琐碎。@AmiTavory不同意。否则您将无法从中获得int\u MAX和类似值。编辑:standard不同意我也不同意,在
[rand.dist.uni.int]
中,它指出:一个
均匀分布
随机数分布产生随机整数i,一个@Revolver\u Ocelot你是对的,谢谢。@user877329:从概念上讲,任何真正的均匀分布都是在两边都开放的间隔上()当然,要知道具体的浮点实现是否允许端点上的点发生,这一点很重要,但这并不需要给它起一个不同于闭区间积分分布的名称。坦率地说,实数分布的良好应用不应该取决于单个粒子是否ar值是否出现。包含或排除范围没有区别,因为获得特定实数(如9)的概率无论如何都是0,因此不会看到9。假定双精度和浮点数在数学意义上不是实数,但考虑到我们讨论的是随机数和flo,这种差异可以忽略不计ats和double只是real的近似值。@nwp因此我也对绘制直方图的通用函数进行了评论。当然是事件的概率,例如[8,9)即使对于类似数学的实数也是非零的。不幸的是,标准库类型的容器会忽略这些事件并集的结果中不可忽略的一部分。在非常实际的意义上,这些签名只是不同而已。@nwp:“无论如何,获得特定实数(如9)的概率为0”--这是不正确的,因为尽管名称
一致实分布
不是实数的连续分布。它是由
RealType
表示的有理数有限子集上的离散分布(默认情况下为
double
)。因此,包括或排除端点确实会产生影响。假定生成特定值的概率通常很小,但例如,如果您的范围是
[1,1+DBL_EPSILON)
那么包含或不包含端点就是两值分布或一值分布之间的差异。无论如何,如果您想获取随机数并执行类似于
1/(端点-x)的操作
对它,那么您关心的是代码崩溃的概率是否很小。而不是
1/(endpoint-x)的分布
是完美的,但如果它有时被零除,情况会更糟……因此你可能会认为标准应该包含端点,用户不应该编写依赖于端点被排除的代码。我真的不知道其中一个或另一个的参数。但它们是否包含端点确实有区别他们决定支持那些希望将其排除在外的使用。
#include <random>
#include <iostream>
#include <type_traits>                                         

template <typename T>
using uniform_distribution =
    typename std::conditional<
        std::is_integral<T>::value,
        std::uniform_int_distribution<T>,
        std::uniform_real_distribution<T>
    >::type;

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

    {
        uniform_distribution<int> u(0, 9);
        bool over_found = false;
        for(size_t i = 0; i < 99999; ++i)
            over_found = over_found || u(gen) >= 9;
        std::cout << std::boolalpha << over_found << std::endl;
    }

    {
        uniform_distribution<float> u(0, 9);
        bool over_found = false;
        for(size_t i = 0; i < 99999; ++i)
            over_found = over_found || u(gen) >= 9;
        std::cout << std::boolalpha << over_found << std::endl;
    }
}