Random Numbers and Random Number Generators In Swift

Many iOS and macOS apps generator random numbers and use random elements to create a dynamic experience for users. This post presents a number of examples for working with random numbers and random number generators in Swift:

  1. Random Number Between Two Values
    a. Random number Between 0 And 1
  2. Swift Random Seed
    a. srand48 and drand48
    b. RandomNumberGenerator
  3. Random Element From Array
    a. Multiple Random Elements From Array
    b. Multiple Random Elements From Array With Replacement
  4. Random Value From Dictionary
    a. Multiple Random Values From Dictionary
    b. Multiple Random Values From Dictionary With Replacement
  5. Generate Unique Random Numbers

Additionally, this post presents Swift random examples for the following types:
a. Random Bool
b. Random CGFloat
c. Random Color
d. Random Data
e. Random Date
f. Random Double
g. Random Enum
h. Random Float
i. Random Int
j. Random String
k. Random UUID

FREE all Swift loading animations.

Loading Animation Example

Follow AdvancedSwift and immediately get access to commented code for these animations that you can use in your projects.

Random Number Between Two Values

Swift numeric types implement a unified random interface random(in:) to generate random numbers between two values:

Int.random(in: 0..<100)
// Example Output: 91

Random number Between 0 And 1

A random number between 0 and 1 is often a decimal, making the Double or Float type more appropriate for generating a decimal random number:

Float.random(in: 0..<1)
// Example Output: 0.9147799

Swift Random Seed

In some cases, generating random numbers in the same order is beneficial. For example, when writing a test case. In this section a random seed will be set in a custom random number generator RandomNumberGeneratorWithSeed so random numbers can be generated in a reliable order.

// Set a random seed for the custom random number generator
var generator = RandomNumberGeneratorWithSeed(seed: 941)

// Use the random number generator with the random seed
// to generate random numbers in the same order
Int.random(in: 0..<100, using: &generator) // 24
Float.random(in: 0..<1, using: &generator) // 0.6942749
[1,2,3,4].randomElement(using: &generator) // 1

srand48 and drand48

Swift’s SystemRandomNumberGenerator manages a seed internally without a way to manually specify a seed. Instead, the srand48 function can be used to set a random seed for the drand48 function. The drand48 function returns a random Double.

// Set a random seed
srand48(314159)

// Generate a seeded random number
drand48() 
// Example Output: 0.4567148644445709

RandomNumberGenerator

To implement a random number generator with a random seed, create a new struct adhering to the RandomNumberGenerator protocol. The constructor should accept an Int seed that is used when calling srand48.

The RandomNumberGenerator protocol requires a next() function to be implemented that returns a random UInt64 value. Both a Double and UInt64 have 8 bytes, so withUnsafeBytes(of:, _:) and load(as:) can be used to transform the random Double from drand48 into a UInt64 with the same bytes:

struct RandomNumberGeneratorWithSeed: RandomNumberGenerator {
    init(seed: Int) {
        // Set the random seed
        srand48(seed)
    }
    
    func next() -> UInt64 {
        // drand48() returns a Double, transform to UInt64
        return withUnsafeBytes(of: drand48()) { bytes in
            bytes.load(as: UInt64.self)
        }
    }
}

Random Element From Array

[1,2,3,4].randomElement()

Multiple Random Elements From Array

var array = [1,2,3,4,5]

// Randomly sorting the array ensures each element
// in the array can appear in the random result once
var randomArray = array.shuffled()

// prefix(3) will return the first 3 elements in the 
// randomArray
randomArray.prefix(3)

Multiple Random Elements From Array With Replacement

Getting multiple random elements from an array with replacement means that elements of the array can appear more than once in the random result:

var array = [1,2,3,4,5]

var randomElements: [Int] = []
for _ in 0..<10 {
    let randomValue = array.randomElement()
    randomElements.append(randomValue)
}

// A more compact implementation for getting 
// multiple random elements from an array with replacement
(0..<10).map { _ in array.randomElement() }

Random Value From Dictionary

var dictionary: [Int:String] = [
    1:"1", 2: "2", 3: "3", 4: "4", 5: "5"
]

// Random Key
dictionary.randomElement()?.key

// Random Value
dictionary.randomElement()?.value

Multiple Random Values From Dictionary

var dictionary: [Int:String] = [
    1:"1", 2: "2", 3: "3", 4: "4", 5: "5"
]

var randomKeys = dictionary.keys.shuffled()
randomKeys.map { key in dictionary[key] }

Multiple Random Values From Dictionary With Replacement

Getting multiple random elements from a dictionary with replacement means that values of the dictionary can appear more than once in the random result:

var dictionary: [Int:String] = [
    1:"1", 2: "2", 3: "3", 4: "4", 5: "5"
]

var randomKeys = dictionary.keys.shuffled()

var randomValues: [String] = []
for _ in 0..<10 {
    let randomKey = dictionary.keys.randomElement()!
    let randomValue = dictionary[randomKey]!
    randomValues.append(randomValue)
}

// A more compact implementation for getting multiple 
// random values from a dictionary with replacement
(0..<10).map { index -> String in
    let randomKey = dictionary.keys.randomElement()!
    return dictionary[randomKey]!
}

Generate Unique Random Numbers

To generate unique random numbers keep track of the random numbers generated using a set:

var uniqueRandomNumbers: Set<Int> = []

while uniqueRandomNumbers.count < 1000 {
    let value = Int.random(in: 0..<100000)
    uniqueRandomNumbers.insert(value)
}

Random Bool

Bool.random()
// Example Output: false

Random CGFloat

CGFloat.random(in: 0..<3.14159)
// Example Output: 2.191631039096155

Random Color

UIColor(
    hue: CGFloat.random(in: 0..<1),
    saturation: CGFloat.random(in: 0..<1),
    brightness: CGFloat.random(in: 0..<1),
    alpha: 1.0
)
// Example Output:
// Red: 0.088
// Green: 0.118
// Blue: 0.953
// Alpha: 1.0

Random Data

let bytes = (0..<10).map { _ in
    UInt8.random(in: 0...UInt8.max)
}
Data(bytes)
// Output is 10 bytes

Random Date

let yearSeconds = 60 * 60 * 24 * 365.0
let timeInterval = Double.random(in: 0..<yearSeconds)

// Random date between now and one year from now
Date(timeInterval: timeInterval, since: Date())
// Example Output: Jul 20, 2021 at 1:47

Random Double

Double.random(in: 0..<3.14159)
// Example Output: 2.37669589020634

Random Enum

One implementation to get a random enum requires the enum to conform to the CaseIterable protocol. In this example, the enum Assignment is defined to conform to CaseIterable:

enum Assignment: CaseIterable {
    case coding
    case debugging
    case ui
    case testing
    case documentation
    case refactoring
}

Another option is to extend an enum to conform to CaseIterable. The CaseIterable protocol has no required methods so only the extension statement is required:

extension Assignment: CaseIterable {}

Enums that conforms to CaseIterable gain an allCases property containing a list of all the available enum cases. To get a random enum, call randomElement() on allCases:

Assignment.allCases.randomElement()
// Example Output: .testing

Random Float

Float.random(in: 0..<3.14159)
// Example Output:0.9225707

Random Int

Int.random(in: 0..<100)
// Example Output: 91

Random String

let letters = "abcdefghijklmnopqrstuvwxyz"
String((0..<10).map { _ in letters.randomElement()! })
// Example Output: aiwlguezgw

Random UUID

UUID().uuidString
// Example Output:
// 25A4DA38-743C-46D0-9B71-1699556C975E

Swift Random Numbers

That’s it! By using RandomNumberGenerator and the unified random(in:) syntax you can generate random numbers, set a seed, get random elements from an array, and generate random values for all kinds of types in Swift.