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:
| 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
| 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
| 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.
