TSR
TSR

Reputation: 20590

Generate a random boolean 70% True, 30% false

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

Answers (3)

Esqarrouth
Esqarrouth

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

Ionică Bizău
Ionică Bizău

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

R. Karpowicz
R. Karpowicz

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:

  • randomTest(100) - 0.5189474703446081
  • randomTest(100) - 0.5189474703446081
  • randomTest(1000) - 0.4973368682657417
  • randomTest(10000) - 0.5001058467610172
  • randomTest(100000) - 0.4987280984186288
  • randomTest(1000000) - 0.4999987387801045
  • randomTest(10000000) - 0.49998292815655454
  • randomTest(100000000) - 0.500079160302315

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

Related Questions