13

乱数を 3 つ生成する必要があり、その量は 1 です。

私の実装では均一な配布がサポートされていません。:(

4

9 に答える 9

27

3 つの乱数を取得し、1 / [数値の合計] である係数を計算します。最後に、各乱数にその係数を掛けます。合計は 1 になります。

于 2011-04-06T09:01:17.483 に答える
11

これは実際には難しい質問です。まず第一に、
Darenの解は 1/3 を超える 2 つの数値をサポートしていないため、均一ではありません。
Simenの解決策は、「乱数を選ぶ」が一様分布から引き出されると仮定すると一様ではありませんが、これはもう少し微妙です。変数間で少なくとも対称的です (つまり、[a, b, c] の確率は、その順列の確率と同じです) が、(1/3, 1/3, 1/ 3)。極端なケースを見て、このように考えてみてください: (1/3, 1/3, 1/3) は、任意の (a, a, a) に由来する可能性があり、a の範囲は 0 から 1 です。(1, 0, 0)、同等に有効なトリプルは、(1, 0, 0) から来ている必要があります。

1 つの解決策:加算して 1 になる正の数のセットは、座標 (1,0,0)、(0,1,0)、(0,0,1) を持つ 3 空間で正三角形を形成します。それを平行四辺形に拡張します。たとえば、点 (1,1,-1) を 4 番目の点として追加します。この double は面積です -- 2 番目の面積を最初の面積にマッピングして、この平行四辺形のランダムな点を選択するだけで十分です。

平行四辺形は、(0,0,1) + A(1,0,-1) + B (0,1,-1) によって均一にサンプリングできます。ここで、A と B の範囲は 0 から 1 まで均一です。

-A

于 2011-07-20T08:49:28.787 に答える
3

0 と 1 の間の 2 つの乱数を生成します。それらをそれぞれ 3 で割ります。3 番目は、1 と 2 つのランダムな 3 分の 1 の差です。

void Main()
{
    Random r = new Random();
    double d1 = r.NextDouble() / 3.0;
    double d2 = r.NextDouble() / 3.0;
    double d3 = 1.0 - d1 - d2;
    System.Console.WriteLine(d1);
    System.Console.WriteLine(d2);
    System.Console.WriteLine(d3);
    System.Console.WriteLine(d1 + d2 + d3);
}

これにより、LINQPad で次のように出力されます。

0.0514050276878934
0.156857372489847
0.79173759982226
1
于 2011-04-06T09:00:36.937 に答える
1

これを行う簡単な方法がありますが、一様乱数を生成できる必要があります。

X を (0,2/3) で一様とする。X < 1/3 の場合、Y = X + 1/3 とします。それ以外の場合は、Y = X - 1/3 とします。Z = 1 - X - Y とします。

この設定では、X、Y、および Z の合計は 1 になり、それらはすべて同じ一様な (0, 2/3) 周辺分布を持ち、3 つのペアワイズ相関はすべて -(1/2) になります。

于 2013-10-03T18:50:53.920 に答える
1

アップデート

  1. 3 つの乱数の vector3 を作成します
  2. ベクトルを正規化する
于 2011-04-06T09:00:53.880 に答える
1

Marnix の回答のわずかなバリエーション:

  1. a[0,1] から乱数を生成する
  2. 2 つの乱数を生成します。x[0,a] およびy[a,1] から
  3. 結果をxy-x、として設定1-y
于 2011-04-06T09:16:00.857 に答える
0

半分の方法:

  • それぞれ長さが PARTS の 0 から 1 の乱数のリストを作成します。
  • リストを合計する
  • 各要素を合計で割る
  • 各要素を丸める
  • 最初の要素を編集して浮動小数点演算を考慮する

申し訳ありませんが、C# はわかりません。Python は次のとおりです。

import random
import time

PARTS       = 5
TOTAL       = 10
PLACES      = 3

def random_sum_split(parts, total, places):

    a = []
    for n in range(parts):
        a.append(random.random())
    b = sum(a)
    c = [x/b for x in a]    
    d = sum(c)
    e = c
    if places != None:
        e = [round(x*total, places) for x in c]
    f = e[-(parts-1):]
    g = total - sum(f)
    if places != None:
        g = round(g, places)
    f.insert(0, g)

    log(a)
    log(b)
    log(c)
    log(d)
    log(e)
    log(f)
    log(g)

    return f   

def tick():

    if info.tick == 1:

        start = time.time()

        alpha = random_sum_split(PARTS, TOTAL, PLACES)

        log('********************')
        log('***** RESULTS ******')
        log('alpha: %s' % alpha)
        log('total: %.7f' % sum(alpha))
        log('parts: %s' % PARTS)
        log('places: %s' % PLACES)

        end = time.time()  

        log('elapsed: %.7f' % (end-start))

収量:

Waiting...
Saved successfully.
[2014-06-13 00:01:00] [0.33561018369775897, 0.4904215932650632, 0.20264927800402832, 0.118862130636748, 0.03107818050878819]
[2014-06-13 00:01:00] 1.17862136611
[2014-06-13 00:01:00] [0.28474809073311597, 0.41609766067850096, 0.17193755673414868, 0.10084844382959707, 0.02636824802463724]
[2014-06-13 00:01:00] 1.0
[2014-06-13 00:01:00] [2.847, 4.161, 1.719, 1.008, 0.264]
[2014-06-13 00:01:00] [2.848, 4.161, 1.719, 1.008, 0.264]
[2014-06-13 00:01:00] 2.848
[2014-06-13 00:01:00] ********************
[2014-06-13 00:01:00] ***** RESULTS ******
[2014-06-13 00:01:00] alpha: [2.848, 4.161, 1.719, 1.008, 0.264]
[2014-06-13 00:01:00] total: 10.0000000
[2014-06-13 00:01:00] parts: 5
[2014-06-13 00:01:00] places: 3
[2014-06-13 00:01:00] elapsed: 0.0054131
于 2014-09-05T01:15:46.493 に答える
0

2/2 メソッド:

  • 0 から 1 までの乱数のリストを作成します。合計にスケーリング
  • リストを小さい順に並べ替えます
  • 最初のリストの各要素間のスペースを測定して、新しいリストを作成します
  • 新しいリストの各要素を丸めます
  • 浮動小数点を考慮して最初の要素を置き換えます

申し訳ありませんが、C# はわかりません。Python では次のようになります。

import random
import time

PARTS       = 5
TOTAL       = 10
PLACES      = 3

def random_sum_split(parts, total, places):


    a = [0.0, total]
    for i in range(parts-1):
        a.append(random.random()*total)
    a.sort()
    b = []
    for i in range(1,(parts+1)):
        b.append(a[i] - a[i-1])
    if places != None:    
        b = [round(x, places) for x in b]  
    c = b[-(parts-1):]
    d = total - sum(c)
    if places != None:
        d = round(d, places)
    c.insert(0, d)

    log(a)
    log(b)
    log(c)
    log(d)

    return c

def tick():

    if info.tick == 1:

        start = time.time()

        alpha = random_sum_split(PARTS, TOTAL, PLACES)

        log('********************')
        log('***** RESULTS ******')
        log('alpha: %s' % alpha)
        log('total: %.7f' % sum(alpha))
        log('parts: %s' % PARTS)
        log('places: %s' % PLACES)

        end = time.time()  

        log('elapsed: %.7f' % (end-start))

収量:

Waiting...
Saved successfully.
[2014-06-13 00:01:00] [0.0, 1.3005056784596913, 3.0412441135728474, 5.218388755020509, 7.156425483589107, 10]
[2014-06-13 00:01:00] [1.301, 1.741, 2.177, 1.938, 2.844]
[2014-06-13 00:01:00] [1.3, 1.741, 2.177, 1.938, 2.844]
[2014-06-13 00:01:00] 1.3
[2014-06-13 00:01:00] ********************
[2014-06-13 00:01:00] ***** RESULTS ******
[2014-06-13 00:01:00] alpha: [1.3, 1.741, 2.177, 1.938, 2.844]
[2014-06-13 00:01:00] total: 10.0000000
[2014-06-13 00:01:00] parts: 5
[2014-06-13 00:01:00] places: 3
[2014-06-13 00:01:00] elapsed: 0.0036860
于 2014-09-05T01:12:18.143 に答える