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:
- Random Number Between Two Values
a. Random number Between 0 And 1 - Swift Random Seed
a.srand48
anddrand48
b.RandomNumberGenerator
- Random Element From Array
a. Multiple Random Elements From Array
b. Multiple Random Elements From Array With Replacement - Random Value From Dictionary
a. Multiple Random Values From Dictionary
b. Multiple Random Values From Dictionary With Replacement - 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
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
In some cases, generating secure random numbers may be required. Read more about using the Security framework to generate 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.