2015-02-04 4 views
1

그들의 확률 값을 갖는 네 개의 정수가 간단한 함수가 무작위 정수를 생성한다 : | 0.41 (2) | 0.29 (3) | 0.25 4 | 1 0.05자바 스크립트 함수는 균일 확률 자바 스크립트 (또는 JQuery와)에서

어떻게 이들 4 가지 숫자를 그들의 가능성을 고려하여 생성 할 수 있습니까? 솔루션이 게시 그러나이 generate random integers with probabilities

: 주석에

function randomWithProbability() { 
    var notRandomNumbers = [1, 1, 1, 1, 2, 2, 2, 3, 3, 4]; 
    var idx = Math.floor(Math.random() * notRandomNumbers.length); 
    return notRandomNumbers[idx]; 
} 

상태를 "동적 notRandomNumbers를 만들 수 (숫자와 자신의 체중/확률을 부여

이 질문은 여기에 게시 된 것과 매우 유사하다) "

내 요구 사항에 충분하지 않습니다. 확률이 10 %, 20 %, 60 %, 10 %라고 할 때 잘 작동합니다.

이 경우 필수 배포로 notRandomNumbers를 구성하는 것이 쉽고 배열 크기가 작습니다. 그러나 확률이 20.354 %, 30.254 % 등일 수있는 일반적인 경우에는 배열 크기가 상황을 정확하게 모델링하는 데 큰 도움이됩니다.

더 일반적인 문제에 대한 해결책이 있습니까?

편집 : 감사의 말 Georg, 해결 방안입니다. 여기 최종 버전은이며, 다른 사람들에게 유용 할 수 있습니다. 각 호출에서 새로운 난수를 얻으려는 추가 추가를 피하기 위해 누적 계산을 별도의 함수로 분할했습니다.

function getRandomBinFromCumulative(cumulative) { 
    var r = Math.random(); 
    for (var i = 0; i < cumulative.length; i++) { 
     if (r <= cumulative[i]) 
      return i; 
    } 
} 
    function getCummulativeDistribution(probs) { 
    var cumulative = []; 
    var sum = probs[0]; 
    probs.forEach(function (p) { 
     cumulative.push(sum); 
     sum += p; 
    }); 
    // the next 2 lines are optional 
    cumulative[cumulative.length - 1] = 1; //force to 1 (if input total was <>1) 
    cumulative.shift(); //remove the first 0 
    return cumulative; 
} 
function testRand() { 
    var probs = [0.1, 0.3, 0.3, 0.3]; 
    var c = getCummulativeDistribution(probs); 
    console.log(c); 
    for (var i = 0; i < 100; i++) { 
     console.log(getRandomBinFromCumulative(c)); 
    } 
} 
+0

예, 누적 분포 함수를 계산하고 값에 따라 간격을 사용하여 개별 임의의 숫자를 가져옵니다. –

답변

2

은 그냥 확률을 축적하고 항목에 대한 current_sum >= random_number을 반환 : 전용 인해 AJ 워커 (전자 편지 (10)에 하나의 비교를 요구하는 우아한 해결책이 있습니다

probs = [0.41, 0.29, 0.25, 0.05]; 
 

 
function item() { 
 
    var r = Math.random(), s = 0; 
 
    for(var i = 0; i < probs.length; i++) { 
 
     s += probs[i]; 
 
     if(r <= s) 
 
      return i; 
 
    } 
 
} 
 

 
// generate 100000 randoms 
 

 
a = []; 
 
c = 0; 
 
while(c++ < 100000) { 
 
    a.push(item()); 
 
} 
 

 
// test actual distibution 
 

 
c = {} 
 
a.forEach(function(x) { 
 
    c[x] = (c[x] || 0) + 1; 
 
}); 
 

 
probs.forEach(function(_, x) { 
 
    document.write(x + "=" + c[x]/a.length + "<br>") 
 
});

1

해당 가중치를 사용하여 두 번째 병렬 배열을 만들고 "휠"알고리즘을 사용하여 색인을 얻습니다.

function randomWithProbability() 
{ 
    var notRandomNumbers = [1,2,3,4]; 

    var w = [0.41, 0.29, 0.25, 0.05]; 
    var placehldr = 0; 
    var maxProb = 0.41; 
    var index = Math.floor(Math.random() * w.length); 
    var i = 0; 

    placehldr = Math.random() * (maxProb * 2); 
    while(placehldr > index) 
    { 
     placehldr -= w[index]; 
     index = (index + 1) % w.length 
    } 

    return (notRandomNumbers[index]); 

} 

이 비디오는 왜 작동하는지에 대한 좋은 설명을 제공합니다. 시각적 표현으로 이해하기 쉽습니다. https://www.youtube.com/watch?v=wNQVo6uOgYA