2016-08-14 145 views
13

我们有uniform_int_distributionuniform_real_distribution,有没有可能包含uniform_distribution,专门在float/double和int/...指定时?为什么没有uniform_distribution?

+9

有一个想法:uniform_int_distribution使用了一个封闭的区间,uniform_real_distribution使用了一个半开放的区间。 – user877329

+0

难道你不能定义你自己的结构并且专门化它吗?这确实很微不足道。 – skypjack

+0

@AmiTavory [参考](http://en.cppreference.com/w/cpp/numeric/random/uniform_int_distribution)不同意。否则,你将无法获得INT_MAX和类似的。编辑:标准不同意,在'[rand.dist.uni.int]'它说:_A'uniform_int_distribution'随机数分布产生随机整数i,a <= i <= b_ –

回答

14

AFAIU,上面的评论由@ user877329和@revolver_ocelot解释正确,而另一个答案是完全错误的。

这是错误的,统一的uniform_intuniform_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; 

那么,如果我们定义uniform_distribution<some_type> u(0, 9),意义是完全不同的:

  • 如果some_type是整数,那么u将输出9大约1/10的时间。

  • 如果some_type不是,则u从未输出9.

下面的代码(其输出为true然后false)说明这一点:

#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; 
    } 
} 

此代码说明使用这个类编写通用代码是危险的。例如,如果您要编写一个通用函数来计算子范围中的结果直方图:[0,1],[1,2,...,[8,9),结果将不兼容。


作为@revolver_ocelot指出,标准库的[inclusive-begin, exclusive_end) convention不能用于均匀整数(因为这将是不可能指定一个均匀的整数随机数生成器生成也最大UINT值),使之成为一个特殊的签名。

+2

包容性或排他性的范围没有区别,因为无论如何,获得特定实数的概率(例如9)总是为0,因此从未看到预期的9。在数学意义上,双打和浮点数并不是真正的数字,但考虑到我们正在讨论随机数和浮点数,浮点数只是可以忽略不计的,浮点数和双精度对于实数而言只是近似值。 – nwp

+0

@nwp因此,我也对绘制直方图的泛函功能发表了评论。即使像数学一样的实数,一个事件如* [8,9)*的概率肯定是非零的。不幸的是,由于这些事件的联合,标准库类型仓将留下不可忽视的部分结果。从实际意义上说,这些签名是不同的。 –

+2

@nwp:“得到某个特定实数的概率,例如9,总是0” - 这是不真实的,因为尽管“uniform_real_distribution”这个名字不是实数上的连续分布。它是由“RealType”(默认为“double”)表示的有理数的有限子集上的离散分布。包括或排除端点因此*确实会有所作为。 –