簡體   English   中英

生成總和為 1 的 N 個數字

[英]Generating N numbers that sum to 1

給定一個大小為n的數組,我想為每個索引生成隨機概率,使得Sigma(a[0]..a[n-1])=1

一種可能的結果可能是:

0     1     2     3     4
0.15  0.2   0.18  0.22  0.25

另一個完全合法的結果可以是:

0     1     2     3     4
0.01  0.01  0.96  0.01  0.01

如何輕松快速地生成這些? 任何語言的答案都很好,首選 Java。

獲取 n 個隨機數,計算它們的總和,並通過將每個數字除以總和將總和歸一化為 1。

你試圖完成的任務無異於從 N 維單位單純形中抽取一個隨機點。

http://en.wikipedia.org/wiki/Simplex#Random_sampling可能會對您有所幫助。

一個簡單的解決方案可能如下:

public static double[] getArray(int n)
    {
        double a[] = new double[n];
        double s = 0.0d;
        Random random = new Random();
        for (int i = 0; i < n; i++)
        {
           a [i] = 1.0d - random.nextDouble();
           a [i] = -1 * Math.log(a[i]);
           s += a[i];
        }
        for (int i = 0; i < n; i++)
        {
           a [i] /= s;
        }
        return a;
    }

為了從 N 維單位單純形中均勻地繪制一個點,我們必須取一個指數分布的隨機變量向量,然后通過這些變量的總和對其進行歸一化。 為了得到一個指數分布的值,我們取一個均勻分布值的負log

這是相對較晚的,但為了顯示對@dreeves 指出的@Kobi 在本文中給出的簡單而直接的答案的修正,這使得采樣統一。 方法(如果我理解清楚的話)是

  1. 從范圍 [1, 2, ... , M-1] 生成 n-1 個不同的值。
  2. 對結果向量進行排序
  3. 添加 0 和 M 作為結果向量的第一個和最后一個元素。
  4. 通過計算 x i - x i-1生成一個新向量,其中 i = 1,2, ... n。 也就是說,新向量由舊向量的連續元素之間的差異組成。
  5. 將新向量的每個元素除以 M。你有你的均勻分布!

我很想知道生成不同的隨機值並通過除以它們的總和將它們歸一化為 1 是否也會產生均勻分布。

如果您想有效地從正態分布生成值,請嘗試Box Muller 變換

獲取 n 個隨機數,計算它們的總和,並通過將每個數字除以總和將總和歸一化為 1。

擴展 Kobi 的答案,這里有一個 Java 函數可以做到這一點。

public static double[] getRandDistArray(int n)  {
    double randArray[] = new double[n];
    double sum = 0;

    // Generate n random numbers
    for (int i = 0; i < randArray.length; i++) {
        randArray[i] = Math.random();
        sum += randArray[i];
    }

    // Normalize sum to 1
    for (int i = 0; i < randArray.length; i++) {
        randArray[i] /= sum;
    }
    return randArray;
}

在測試運行中, getRandDistArray(5)返回以下內容

[0.1796505603694718, 0.31518724882558813, 0.15226147256596428, 0.30954417535503603, 0.043356542883939767]
public static double[] array(int n){

    double[] a = new double[n];
    double flag = 0;

    for(int i=0;i<n;i++){
        a[i] = Math.random();
        flag += a[i];
    }

    for(int i=0;i<n;i++) a[i] /= flag;

    return a;
}

在這里,首先a存儲隨機數。 並且flag將保留所有生成的數字的總和,以便在下一個 for 循環中生成的數字將除以flag ,最后數組將具有概率分布的隨機數。

暫無
暫無

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

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