N個の大理石があるモデルをシミュレートしています。 N個の大理石の中からn個の大理石を選び、n個のピックアップされたもののうちの正確にk個が良いという確率が求められる。超幾何シミュレーションでは、一度にシャッフルして一度にピッキングすると間違った結果になります
私はこの2つのやり方をしました。どちらも、私はK 'の真値とN-Kの偽値を含む配列を生成しました。しかし、最初の方法では、私はこの配列をシャッフルして最初の値を取り出し、どれくらいが「真」であるのかを数えました。 2番目の方法では、インデックスをランダムに選択し、配列からその要素を削除し、このn回ループしました(もちろん、実際の要素を数える)。
結果の分布はHyperGeometric(N, K, n)である必要があります。最初の方法は私に間違った結果をもたらしたが、2番目の方法は正しい結果を与えた。シャッフルされた配列の最初の要素を選んでも問題ないのですが、何が間違っていますか?ここに私のJavascriptのコードは次のとおりです。
黄色の点:
function pickGoodsTest(N, K, n) {
var origArr = generateArr(N, i=> i<K);
shuffle(origArr);
var goods = 0;
for (let i=0; i<n; i++) if(origArr[i]) goods++;
return goods;
}
function pickGoodsTest2(N, K, n) {
var origArr = generateArr(N, i=> i<K);
var goods = 0;
for (let i=0; i<n; i++) {
let rndInd = randInt(0, origArr.length-1);
let wasGood = origArr.splice(rndInd, 1)[0];
if (wasGood) goods++;
}
return goods;
}
//helper functions:
function generateArr(len, indFunc) {
var ret = [];
for (let i=0; i<len; i++) {
ret.push(indFunc(i));
}
return ret;
}
function randInt(a, b){return a+Math.floor(Math.random()*(b-a+1));}
function shuffle(arr) {
let arrLen = arr.length;
for (let i=0; i<arrLen; i++) {
let temp = arr[i];
let rndInd = randInt(0, arrLen-1);
arr[i] = arr[rndInd];
arr[rndInd] = temp;
}
}
は、これらの値と結果のプロットN = 10、K = 6、N = 5(シミュレート500000回)です超幾何平均pmfの値である。
ありがとうございます!私は、それが偏っているかどうかを考えずに、常に以前のシャフリングの方法を使用してきました。 Fisher-Yatesのシャッフルは正しい結果を生み出します(Wikipediaの言うように偏っているので、期待どおり)。 – ploosu2