2016-08-14 64 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」)表示的有理數的有限子集上的離散分佈。包括或排除端點因此*確實會有所作爲。 –