Swift and Random Numbers: Magic That Works Predictably
\n\nEvery developer sooner or later faces the task: "How to generate a random number?". It seems simple, right? But in the world of Swift, this topic has come a long way — from ancient C functions to an elegant built-in API. In this article, we will cover all the ways to generate random numbers in Swift, from simple to industrial, with live examples and important nuances.
\n\nIf you've ever wondered why your arc4random() returns strange numbers or how to make a truly random selection from an array — you've come to the right place. Let's go!
A Brief History: How We Got Here
\n\nBefore Swift 4.2 (2018), developers painfully chose between arc4random(), drand48(), and workarounds like rand() % 100. The latter, by the way, was dangerous — bias in distribution is guaranteed if the range is not evenly divisible by RAND_MAX. With the release of Swift 4.2, Apple gave us the RandomNumberGenerator protocol and built-in methods. Now generating random numbers is safe, readable, and uniform.
The Modern Way: RandomNumberGenerator and Type Methods
\n\nStarting with Swift 4.2, the most correct and simple way is to use static methods on types:
\n\n// Random integer from 1 to 100\nlet randomInt = Int.random(in: 1...100)\n\n// Random floating-point number from 0.0 to 1.0\nlet randomDouble = Double.random(in: 0.0...1.0)\n\n// Random Float number\nlet randomFloat = Float.random(in: 0.0...1.0)\n\n// Random Bool\nlet randomBool = Bool.random()\n\n\nThis API uses the system generator SystemRandomNumberGenerator, which is cryptographically secure (but more on that later). Important: the range is specified via a closed range (...) or a half-open range (..<).
Why is this cool?
\n- \n
- Type safety — the compiler won't let you generate a Double and assign it to an Int. \n
- No bias — Swift itself takes care of uniform distribution. \n
- Versatility — works for all numeric types: Int, UInt, Int8, Float, Double, CGFloat, and even Bool. \n
Generating a Random Number from a Range: Pitfalls
\n\nWhat could go wrong? Consider the example:
\n\nlet diceRoll = Int.random(in: 1...6) // Dice: 1,2,3,4,5,6\nlet coinFlip = Int.random(in: 0..<2) // Coin: 0 or 1\n\n\nEverything is correct. But if you want to generate a random number without an upper bound (for example, from 0 to infinity) — that won't work. Swift requires an explicit range. This is done on purpose to avoid overflow errors.
\n\nIf you need a random number from 0 to max (where max is a variable), simply use:
let maxValue = 500\nlet randomUpTo = Int.random(in: 0...maxValue)\n\n\nRandom Element from a Collection (Array, Set, Dictionary)
\n\nGenerating a random number is often needed not for its own sake, but to select a random element. Swift provides an elegant solution:
\n\nlet fruits = ["apple", "banana", "cherry", "melon"]\nif let randomFruit = fruits.randomElement() {\n print("Today we eat \\(randomFruit)")\n} else {\n print("The basket is empty!")\n}\n\n\nThe randomElement() method returns an optional value — this is important because the collection can be empty. To shuffle the entire array, use shuffled():
let shuffledFruits = fruits.shuffled()\nprint(shuffledFruits) // for example: ["banana", "melon", "apple", "cherry"]\n\n\nCryptographically Secure Generation: When Security is Paramount
\n\nThe standard I