3

I am trying to make a static extension of Bool to return a random true/false value whenever called. I am trying to make this work:

static func coinFlip() -> Bool {
    #if os(Linux)
    srand(UInt32(time(nil)))
    let result = Int(random() % 2)
    if result == 0 {
        return false
    } else {
        return true
    }
    #else
    return arc4random_uniform(2) == 0
    #endif
}

I am using this within the scope of a route being called in a Server Side Swift application. Whenever it is called for the first time, it does return a random value, but all subsequent calls to the function in the same scope don't randomize the output. For example:

for _ in 1...5 {
    let coin = Bool.coinFlip()
    if coin == true {
        print("coin flip true")
    } else {
        print("coin flip false")
    }
}

...yields an output of this:

coin flip false
coin flip false
coin flip false
coin flip false
coin flip false

...but then if I call the route again separately, I could get:

coin flip true
coin flip true
coin flip true
coin flip true
coin flip true

Is it a problem with srand(UInt32(time(nil))) only randomizing the pseudo-random sequence of random()? I'm not sure what to do. Thanks in advance for your help!

dokun1
  • 2,120
  • 19
  • 37

2 Answers2

4

time(nil)) returns the current time as a number of seconds, which means that you seed the random number generator with the same value when the method is called multiple times within a one second interval.

You should call srand(UInt32(time(nil))) only once on application startup, not on each call of coinFlip().

In addition, the function can be simplified a bit, and I would call it random(), not coinFlip():

#if os(Linux)
    srand(UInt32(time(nil)))
#endif

extension Bool {
    static func random() -> Bool {
        #if os(Linux)
            return Glibc.random() % 2 == 0
        #else
            return arc4random_uniform(2) == 0
        #endif
    }
}

for _ in 1...5 {
    print(Bool.random())
}
Martin R
  • 529,903
  • 94
  • 1,240
  • 1,382
0

Starting with Swift 4.2, there is a native way to do this:

let flippedCoin = Bool.random()

Documentation: https://developer.apple.com/documentation/swift/bool/2994861-random

Cœur
  • 37,241
  • 25
  • 195
  • 267