40

I'm needing to create a random bool value in my game, in Swift.

It's basically, if Yes (or 1), spawn one object, if No (or 0), spawn the other.

So far, looking at this question and a similar one on here, I found this:

let randomSequenceNumber = Int(arc4random_uniform(2))

Now it works, but it seems bias to 0 to me... like ridiculously bias...

This is how I'm then using the value:

if(randomSequenceNumber == 0)
    //spawn object A
else
    //spawn object B

Is there a better way to implement this using a random bool value? That isn't bias to a certain value?

Update

Bit of an experiment to see how many 1's vs 0's were were generated in 10,000 calls:

func experiment() {
    var numbers: [Int] = []
    var tester: Int = 0
    var sum = 0

    for i in 0...10000 {
        tester = Int(arc4random_uniform(2))
        numbers.append(tester)
        print(i)
    }

    for number in numbers {
        sum += number
    }

    print("Total 1's: ", sum)
}

Test 1: Console Output: Total 1's: 4936
Test 2: Console Output: Total 1's: 4994
Test 3: Console Output: Total 1's: 4995
Cœur
  • 37,241
  • 25
  • 195
  • 267
Reanimation
  • 3,151
  • 10
  • 50
  • 88
  • I tried using that function in a playground by counting the number of zero and one results for 10,000 calls. I definitely don't see the bias you're experiencing. (More like +/- 1.2% either direction) Are there any other conditions in your app that could be influencing the result? – Phillip Mills Dec 12 '15 at 15:24
  • Really? Maybe it just seems bias then... maybe, it's not random enough (or evenly distributed enough) if you know what I mean :( – Reanimation Dec 12 '15 at 15:37
  • Try it! See if you get the same result in your environment. – Phillip Mills Dec 12 '15 at 15:42
  • In 10,000 calls, I got `4936` 1's and the rest 0's... I guess it is pretty even, just doesn't seem it. I added the test to my question incase anyone wonders how I did it. – Reanimation Dec 12 '15 at 15:55
  • 1
    what did you expect? let imagine that you have a function which gives you sequence true, false, true, false, ......... true and false will be 'perfectly' distributed, but unfortunately NOT randomly!! your test has no value to see, if arc4random_uniform is really good or not for your application. generally there is a lot of criteria, some of them could be very specific to the problem which should be solved. – user3441734 Dec 12 '15 at 19:16
  • That makes no sense to me... I don't have a function that generates that sequence, so it's irrelevant. Could you expand on your definition of "good or not"? `arc4random` is created exactly for this type of application, the fact I'm using 0 and 1 to represent bool vales don't change that. Which criteria would be more specific? – Reanimation Dec 12 '15 at 23:56
  • 1
    i try to explain you, that even thought you run it 10000 times, you can not expect that you will receive 5000 true and 5000 false. what you want is probability of 50% in every single call of you function. – user3441734 Dec 13 '15 at 06:55

3 Answers3

81

Xcode 10 with Swift 4.2

Looks like Apple  engineers are listening

let randomBool = Bool.random()
Warif Akhand Rishi
  • 23,920
  • 8
  • 80
  • 107
57
import Foundation

func randomBool() -> Bool {
    return arc4random_uniform(2) == 0
}

for i in 0...10 {
    print(randomBool())
}

for more advanced generator the theory is available here

for basic understanding of Bernoulli (or binomial) distribution check here

GregP
  • 1,584
  • 17
  • 16
user3441734
  • 16,722
  • 2
  • 40
  • 59
  • 1
    This is nicer code for sure, so I've changed mine to `let randomSequenceNumber = Int(arc4random_uniform(2)) == 0 ? true: false` – Reanimation Dec 12 '15 at 15:38
  • 1
    up to you, creating an Int is not necessary at all ... the distribution is good enough for almost any application. if you are still not happy with it, check the theory from the link i provide for you – user3441734 Dec 12 '15 at 15:40
  • Oh I read somewhere it's good practice to cast to int to remove absolute bias-ness. Either way, definitely better way. I will indeed check that document. Thank you for posting. – Reanimation Dec 12 '15 at 15:42
  • The random result in for statement is ***NOT random***, it's up to the time/mini-seconds. – Itachi Jul 25 '17 at 03:11
17
extension Bool {
    static func random() -> Bool {
        return arc4random_uniform(2) == 0
    }
}

// usage:
Bool.random()
Adam Waite
  • 19,175
  • 22
  • 126
  • 148