Getting a random number within a range is a very common operation. There are multiple ways of extending Swift language to add support for getting random values within a specified range. After experimenting with different implementations like utility functions, integer and float extensions I have found that the most natural way of doing it is to extend ClosedRange. This will allow to write a very readable code:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
let randomDouble: Double = (-0.3...0.9).random | |
let randomCGFloat: CGFloat = (-0.9...0.9).random | |
let randomInt: Int = (-9...3).random | |
let randomUInt: UInt = (3...9).random |
Random floating point values
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
extension ClosedRange where Bound: BinaryFloatingPoint { | |
var random: Bound { | |
let ratio = Bound(arc4random_uniform(UInt32.max)) / Bound(UInt32.max - 1) | |
let offset = (upperBound - lowerBound) * ratio | |
return lowerBound + offset | |
} | |
} |
1. Get a random value using a max possible range (note that arc4random_uniform excludes the upper bound).
2. Convert the value to percentage.
3. Multiply the range with the percentage.
4. Add offset to the range’s minimum value.
Random integer values
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
extension ClosedRange where Bound: BinaryInteger { | |
var random: Bound { | |
let offset = arc4random_uniform(UInt32(upperBound - lowerBound) + 1) | |
return lowerBound + Bound(offset) | |
} | |
} |
1. Get a random value from the allowed range.
2. Add the offset to the range’s minimum value.