簡體   English   中英

有偏隨機數發生器

[英]Biased Random Number Generator

我正在尋找可以產生偏差的隨機數生成器。 例如,假設我想要一個 1-5 之間的隨機數,概率為:

1:出現 20% 的時間
2:出現 10% 的時間
3:出現 40% 的時間
4:有 25% 的時間出現
5: 5% 的時間出現

標准庫或其他庫中是否有任何東西可以做到這一點? 或者,有沒有一種有效的方法可以自己做到這一點?

對於您的問題,只需從此列表中統一選擇一個隨機元素即可:

[1, 1, 1, 1, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5]

通常,請檢查以下答案: 加權隨機數


在TR1和C ++ 0x中,存在<random> ,其中包含discrete_distribution生成此類編號等。

您可能還想查看GSL,它包含比標准<random>庫更多的隨機分布 (和隨機數生成器)。 (但請注意,GSL使用GPLv3。)

最好的方法可能是只使用普通的無偏隨機生成器,然后根據其值落入的間隔返回。

只是一個if語句,給出1表示0:0.2,2表示0.2:0.3,3表示0.3:0.7,4表示0.7:0.95,5表示0.95:1。 最好將間隔的下限或上限定為包含和不包含另一個。

int biasedRandom(){
double i = randomNumber();
if(i<= 0.2){return 1;}
else if(i <= 0.3){return 2;}
else if(i <= 0.7){return 3;}
else if(i <= 0.95){return 4;}
else{return 5;}
}

這樣的事情。

Boost隨機數庫提供了為發電機指定不同形狀分布的功能。 這是一個很棒的庫-請參閱http://www.boost.org/doc/libs/1_42_0/libs/random/index.html

您所描述的是根據特定概率分布得出的隨機數生成器的實現。 例如,來自高斯分布的繪圖數字應繪制隨機數,以使特定繪圖的概率x 替代文字
(來源: wikimedia.org

通常,方法是從均勻隨機分布中提取,然后在該繪制位置選擇所需分布的累積分布函數(CDF)的值。 對於高斯正態分布,從均勻分布中繪制一個隨機數x (這是標准隨機數生成器應提供的),然后選擇 替代文字 作為隨機的高斯分布值。 對於您的情況,您描述的CDF是一個分段的連續階梯函數,可以使用已經收到的許多(正確)答案中的任何一個來實現。

當然,這都是瑣事。 應該使用已為您處理此問題的庫。 統計數據和隨機數的生成並非易事,因此無需重新發明輪子。 請參閱尼爾的答案(並查看Boost 隨機數庫)。

遲到了這個派對。 這是C ++ 0x答案:

#include <iostream>
#include <random>
#include <iterator>

int main()
{
    // Set up distribution
    double interval[] = {1,   2,   3,   4,   5,   6};
    double weights[] = {  .2,   .1,  .4,  .25, .05};
    std::piecewise_constant_distribution<> dist(std::begin(interval),
                                                std::end(interval),
                                                std::begin(weights));
    // Choose generator
    std::mt19937 gen;  // seed as wanted
    // Demonstrate by pouring into avg[rand-1]
    const unsigned N = 1000000;
    double avg[sizeof(weights) / sizeof(weights[0])] = {0};
    for (unsigned i = 0; i < N; ++i)
        avg[static_cast<unsigned>(dist(gen)) - 1]++;
    // Comute averages
    for (double* i = std::begin(avg); i < std::end(avg); ++i)
        *i /= N;
    // Display
    for (unsigned i = 1; i <= sizeof(avg)/sizeof(avg[0]); ++i)
        std::cout << "avg[" << i << "] = " << avg[i-1] << '\n';
}

對我來說輸出:

avg[1] = 0.199779
avg[2] = 0.100002
avg[3] = 0.400111
avg[4] = 0.250257
avg[5] = 0.049851

為什么不只使用返回0.0到1.0之間的數字的常規隨機數生成器,然后將其包裝到另一個根據您的要求返回數字的函數中呢?

喜歡

double biased (double seed) {
if (seed >= 0.0 && seed <0.2) return 1;
else if  ...
}

if 0< x<0.2 return 1if 0.2<x <0.3 return 2if 0.2<x <0.3 return 2隨機實數x放入[0,1]。

有關一般問題,請參見此處

肯尼(Kenny)根據您的特定頻率分布提供了適當的答案。

更為籠統的答案是對數據使用CDF(累積分布函數),並使用統一的隨機數來選擇分布內的值。

#include <boost/random/discrete_distribution.hpp>
#include <boost/random/mersenne_twister.hpp>
#include <boost/random/variate_generator.hpp>

#include <iostream>

int main()
{

  unsigned int seed = 42;
  boost::mt19937 generator(seed);

  // return 0 with probability 10%
  //        1                  40%
  //        2                  50%
  boost::random::discrete_distribution<int> custom_dist{1,4,5};

  boost::variate_generator<boost::mt19937&,
  boost::random::discrete_distribution<int> > rndn(generator, custom_dist);

  for (unsigned int i = 0; i<10000; i++) {
    std::cout << rndn() << std::endl;
  }

  return 0;

}

這是結果圖:

輸出量

我正在做同樣的事情,發現了這一點: http : //eli.thegreenplace.net/2010/01/22/weighted-random-generation-in-python/

似乎足以滿足您指定的目的。

我一直在為 TypeScript 尋找類似的東西,但只為 C 找到了這個問題。

所以這是我在 TypeScript 中提出的一個有偏隨機數生成器,以防萬一有人在 TypeScript 中需要這樣的東西。我相信你可以以某種方式將它翻譯成 C。

export async function weightedRandomItem<T>(list: { weight: number; item: T }[]): Promise<T> {
    const weightSum = sumBy(list, (item) => item.weight)
    const randomIndex = await randomIntegerBetween(1, weightSum)

    let currentIndex = 1
    for (const listItem of list) {
        if (randomIndex >= currentIndex && randomIndex < currentIndex + listItem.weight) {
            return listItem.item
        }
        currentIndex += listItem.weight
    }
    throw new Error("No item selected. Impossible.")
}

其中randomIntegerBetween(minInclusive: number, maxInclusive: number)返回隨機 integer。

在這種情況下, sumBy()lodash function ,它應該是不言自明的。

作為輸入,您可以傳遞以下內容:

[{
    weight: 10,
    item: 1,
},
{
    weight: 50,
    item: 2,
},
{
    weight: 30,
    item: 3,
},
{
    weight: 10,
    item: 4,
}]

那么,結果很可能是2

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM