Reputation: 20590
I have the following function that generates a random boolean. choose_direction: function () {
var random_boolean = Math.random() >= 0.5;
if (random_boolean) {
trade.call()
prev_trade.goingUp = true
console.log('Trade: CALL!!!!!!!!!!!!!!!!!!!!!!')
} else {
trade.put()
prev_trade.goingUp = false
console.log('Trade: PUT!!!!!!!!!!!!!!!!!!!!!!!!')
}
}
However, I need the distribution to be unfair. More specifically, I want the output to be 70% of the time true and 30% of the time false.
Upvotes: 10
Views: 13812
Reputation: 39201
Here is a version I made with typescript
. Can easily remove the variable types to turn this into javascript
.
//Usage
let randomBoolean = randomPercentForTrue(70)
export function randomPercentForTrue(percentage: number): boolean {
return randomNumber(1, 100) <= percentage
}
export function randomNumber(minValue: number, maxValue: number): number {
return Math.floor(Math.random() * (maxValue - minValue + 1)) + minValue
}
These methods are heavily tested with various use cases. Here are test cases with mocha:
it('randomPercentForTrue with 95% accuracy', function() {
let results0: boolean[] = []
let results1: boolean[] = []
let results2: boolean[] = []
let results3: boolean[] = []
let results4: boolean[] = []
let loopAmount = 10000
for(let i = 0; i < loopAmount; i++) {
results0.push(randomPercentForTrue(0))
results1.push(randomPercentForTrue(25))
results2.push(randomPercentForTrue(50))
results3.push(randomPercentForTrue(75))
results4.push(randomPercentForTrue(100))
}
let resultTotals = Array(5).fill(0)
for(let i = 0; i < loopAmount; i++) {
resultTotals[0] += results0[i]
resultTotals[1] += results1[i]
resultTotals[2] += results2[i]
resultTotals[3] += results3[i]
resultTotals[4] += results4[i]
}
expect(resultTotals[0]).to.be.closeTo(0, 0)
expect(resultTotals[1]).to.be.closeTo(loopAmount * 25 / 100, loopAmount * 25 / 100 / 20)
expect(resultTotals[2]).to.be.closeTo(loopAmount * 50 / 100, loopAmount * 50 / 100 / 20)
expect(resultTotals[3]).to.be.closeTo(loopAmount * 75 / 100, loopAmount * 75 / 100 / 20)
expect(resultTotals[4]).to.be.closeTo(loopAmount, 0)
})
Upvotes: 0
Reputation: 113455
Instead of >= 0.5
you just need < 0.7
:
var random_boolean = Math.random() < 0.7;
// 70% this will be true, 30% false
As @plasmacel commented, Math.random()
returns a value between 0
and 1
(including 0
, but not 1
: [0, 1)
), so therefore we do < 0.7
.
Upvotes: 31
Reputation: 9
Let's consider one thing. Math.random() gives you a pseudo-random number.
Try this function:
function randomTest(triesCount) {
var sum = 0;
for(var i = 0; i < triesCount; i++){
sum += Math.random();
}
return sum / triesCount;
}
if you try it with different triesCount parameters the results will be:
So as you can se the results go to 0.5 which means this is not a random number generated here.
Although the answer to your question will be
var random_boolean = Math.random() >= 0.3;
as Ionică Bizău said.
But keep in mind that it is pseudo-random number!
Upvotes: 0