Swift: Random number for 64-bit integers?

Update: As of Swift 4.2 (distributed with Xcode 10.1) there is a unified random API in the Swift standard library, see

You can simply call

UInt64.random(in: minValue ... maxValue)

to get a random number in the given range.


(Previous answer for Swift < 4.2:) With arc4random_buf() you can create “arbitrary large” random numbers,
so this would be a possible solution:

// Swift 2:
func random64(upper_bound: UInt64) -> UInt64 {

    // Generate 64-bit random number:
    var rnd : UInt64 = 0
    arc4random_buf(&rnd, sizeofValue(rnd))

    return rnd % upper_bound
}

// Swift 3:
func random64(upper_bound: UInt64) -> UInt64 {

    // Generate 64-bit random number:
    var rnd : UInt64 = 0
    arc4random_buf(&rnd, MemoryLayout.size(ofValue: rnd))

    return rnd % upper_bound
}

This method suffers from the “modulo bias” problem when the upper bound is not a power of 2 (See Why do people say there is modulo bias when using a random number generator?). Here I have translated the answer
https://stackoverflow.com/a/10989061/1187415 from above thread to Swift:

// Swift 2:
func random64(upper_bound: UInt64) -> UInt64 {

    // Generate 64-bit random value in a range that is
    // divisible by upper_bound:
    let range = UInt64.max - UInt64.max % upper_bound
    var rnd : UInt64 = 0
    repeat {
        arc4random_buf(&rnd, sizeofValue(rnd))
    } while rnd >= range

    return rnd % upper_bound
}

// Swift 3:
func random64(upper_bound: UInt64) -> UInt64 {

    // Generate 64-bit random value in a range that is
    // divisible by upper_bound:
    let range = UInt64.max - UInt64.max % upper_bound
    var rnd : UInt64 = 0
    repeat {
        arc4random_buf(&rnd, MemoryLayout.size(ofValue: rnd))
    } while rnd >= range

    return rnd % upper_bound
}

(At first sight it looks as if the loop might not terminate, but it can be shown
that on average less than 2 iterations are needed.)

Leave a Comment