Reputation: 329
I am having some strange bug, which I cannot grasp where it comes from. I am writing it in js in Google Script environment.
function tester() {
var pdf = [[0,5],[1,5],[2,40],[3,50]]; // some pdf as a 2d array
var tuple = [0,0,0,0]; //the resulting pdf from the test
var rand = 0;
for (var i = 0; i<100; i++){ //100 times initialize a random variable and then catch the result into the tuple
rand = getRandomN(pdf);
if (rand==0){tuple[0]+=1} //if the outcome==0 then add 1 to the first element of the tuple
else if (rand==1){tuple[1]+=1}
else if (rand==2){tuple[2]+=1}
else if (rand==3){tuple[3]+=1}
}
Logger.log(tuple);
}
getRandomN(pdf)
returns one outcome according to the pdf
The problem is that the tuple always returns all zeros with 1 at some of the places. It looks like the randomizer works just fine, but looping is gone through only once. Does anyone have a hint?
UPDATE:
function getRandomN(pdf) {
var result = 0;
var rand = getRandomInt(0,10000)/100;
for (var i=1; i<pdf.length; i++){
pdf[i][1] = pdf[i][1] + pdf[i-1][1];
}
if (pdf[pdf.length-1][1] != 100){return undefined}
//Logger.log(rand);
for (var i=0; i<pdf.length; i++){
if (rand<=pdf[i][1]){result=pdf[i][0]; break}
}
Logger.log(pdf);
return result;
}
And the standard function from the Mozilla
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min)) + min;
}
Upvotes: 0
Views: 74
Reputation: 329
I think I know why. Because the scope of pdf is exactly global within the tester()
and I am changing it within the getRandomN(pdf)
, hence, it is increasing all the time, and after the first run it gets updated and I am calculating already from a new pdf, where the last element of the pdf (i.e. cdf) will never be equal to 100.
UPDATE:
Just if you are interested in the correct code that is working. The part of mapping pdf to cdf is not the most beautiful one. I'd appreciate improvement hints, but it works just fine. Kudos to the contributors for pointing into the right direction.
function getRandomN(pdf) {
var result = 0;
var rand = getRandomInt(0,10000)/100;
var cdf = [];
//construct the cdf
for (var i=1; i<pdf.length; i++){
//handle the first unchanged element
cdf[0]=[];
cdf[0][1] = pdf[0][1];
cdf[0][0] = pdf[0][0];
cdf[i]=[];
cdf[i][1] = pdf[i][1] + cdf[i-1][1];
cdf[i][0] = pdf[i][0];//add all outcomes to the array's first column
}
if (cdf[cdf.length-1][1] != 100){return undefined}
//Logger.log(rand);
for (var i=0; i<cdf.length; i++){
if (rand<=cdf[i][1]){result=cdf[i][0]; break}
}
//Logger.log(cdf);
return result;
}
Upvotes: 0
Reputation: 11859
The reason for this is:
if (pdf[pdf.length-1][1] != 100){return undefined;}
here you are returning undefined if you return 0 or any of rand first index
then it will display proper tuple
and you can see the loop count.
try running this:
function tester() {
var pdf = [[0,5],[1,5],[2,40],[3,50]]; // some pdf as a 2d array
var tuple = [0,0,0,0]; //the resulting pdf from the test
var rand = 0;
for (var i = 0; i<100; i++){ //100 times initialize a random variable and then catch the result into the tuple
rand = getRandomN(pdf);
tuple[rand] += 1;
}
console.log(tuple);
document.write(tuple);
}
function getRandomN(pdf) {
var result = 0;
var rand = getRandomInt(0,10000)/100;
// console.log(rand);
for (var i=1; i<pdf.length; i++){
pdf[i][1] = pdf[i][1] + pdf[i-1][1];
}
if (pdf[pdf.length-1][1] != 100){return 0;}//return any of 0,1,2,3 to test your code.
for (var i=0; i<pdf.length; i++){
if (rand<=pdf[i][1]){result=pdf[i][0]; break}
}
// console.log(pdf);
return result;
}
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min)) + min;
}
tester();
Upvotes: 1