Swift 4.2+
Swift 4.2 shipped with Xcode 10 introduces new easy-to-use random functions for many data types. You can call the random()
method on numeric types.
let randomInt = Int.random(in: 0..<6)
let randomDouble = Double.random(in: 2.71828...3.14159)
let randomBool = Bool.random()
Use arc4random_uniform(n)
for a random integer between 0 and n-1.
let diceRoll = Int(arc4random_uniform(6) + 1)
Cast the result to Int so you don't have to explicitly type your vars as UInt32
(which seems un-Swifty).
0
. In your code, diceRoll
could be 0
. Just saying...
Int(arc4random_uniform(6)+1)
.
arc3random_uniform(n)
to a UInt32(n)
if you are using a value that isn't already of that type.
Edit: Updated for Swift 3.0
arc4random
works well in Swift, but the base functions are limited to 32-bit integer types (Int
is 64-bit on iPhone 5S and modern Macs). Here's a generic function for a random number of a type expressible by an integer literal:
public func arc4random<T: ExpressibleByIntegerLiteral>(_ type: T.Type) -> T {
var r: T = 0
arc4random_buf(&r, MemoryLayout<T>.size)
return r
}
We can use this new generic function to extend UInt64
, adding boundary arguments and mitigating modulo bias. (This is lifted straight from arc4random.c)
public extension UInt64 {
public static func random(lower: UInt64 = min, upper: UInt64 = max) -> UInt64 {
var m: UInt64
let u = upper - lower
var r = arc4random(UInt64.self)
if u > UInt64(Int64.max) {
m = 1 + ~u
} else {
m = ((max - (u * 2)) + 1) % u
}
while r < m {
r = arc4random(UInt64.self)
}
return (r % u) + lower
}
}
With that we can extend Int64
for the same arguments, dealing with overflow:
public extension Int64 {
public static func random(lower: Int64 = min, upper: Int64 = max) -> Int64 {
let (s, overflow) = Int64.subtractWithOverflow(upper, lower)
let u = overflow ? UInt64.max - UInt64(~s) : UInt64(s)
let r = UInt64.random(upper: u)
if r > UInt64(Int64.max) {
return Int64(r - (UInt64(~lower) + 1))
} else {
return Int64(r) + lower
}
}
}
To complete the family...
private let _wordSize = __WORDSIZE
public extension UInt32 {
public static func random(lower: UInt32 = min, upper: UInt32 = max) -> UInt32 {
return arc4random_uniform(upper - lower) + lower
}
}
public extension Int32 {
public static func random(lower: Int32 = min, upper: Int32 = max) -> Int32 {
let r = arc4random_uniform(UInt32(Int64(upper) - Int64(lower)))
return Int32(Int64(r) + Int64(lower))
}
}
public extension UInt {
public static func random(lower: UInt = min, upper: UInt = max) -> UInt {
switch (_wordSize) {
case 32: return UInt(UInt32.random(UInt32(lower), upper: UInt32(upper)))
case 64: return UInt(UInt64.random(UInt64(lower), upper: UInt64(upper)))
default: return lower
}
}
}
public extension Int {
public static func random(lower: Int = min, upper: Int = max) -> Int {
switch (_wordSize) {
case 32: return Int(Int32.random(Int32(lower), upper: Int32(upper)))
case 64: return Int(Int64.random(Int64(lower), upper: Int64(upper)))
default: return lower
}
}
}
After all that, we can finally do something like this:
let diceRoll = UInt64.random(lower: 1, upper: 7)
var r = arc4random(UInt64)
. Please advice what did you mean here?
arc4random
(defined in the first code block) with the argument UInt64
which is a Type
.
arc4random_buf
. The purpose of these extensions is to do exactly what arc4random_uniform
does (mitigate modulo bias) except for 64-bit types.
Edit for Swift 4.2
Starting in Swift 4.2, instead of using the imported C function arc4random_uniform(), you can now use Swift’s own native functions.
// Generates integers starting with 0 up to, and including, 10
Int.random(in: 0 ... 10)
You can use random(in:)
to get random values for other primitive values as well; such as Int, Double, Float and even Bool.
Swift versions < 4.2
This method will generate a random Int
value between the given minimum and maximum
func randomInt(min: Int, max: Int) -> Int {
return min + Int(arc4random_uniform(UInt32(max - min + 1)))
}
I used this code:
var k: Int = random() % 10;
random is unavailable in Swift: Use arc4random instead.
As of iOS 9, you can use the new GameplayKit classes to generate random numbers in a variety of ways.
You have four source types to choose from: a general random source (unnamed, down to the system to choose what it does), linear congruential, ARC4 and Mersenne Twister. These can generate random ints, floats and bools.
At the simplest level, you can generate a random number from the system's built-in random source like this:
GKRandomSource.sharedRandom().nextInt()
That generates a number between -2,147,483,648 and 2,147,483,647. If you want a number between 0 and an upper bound (exclusive) you'd use this:
GKRandomSource.sharedRandom().nextIntWithUpperBound(6)
GameplayKit has some convenience constructors built in to work with dice. For example, you can roll a six-sided die like this:
let d6 = GKRandomDistribution.d6()
d6.nextInt()
Plus you can shape the random distribution by using things like GKShuffledDistribution. That takes a little more explaining, but if you're interested you can read my tutorial on GameplayKit random numbers.
import GameplayKit
. Swift 3 changed the syntax to GKRandomSource.sharedRandom().nextInt(upperBound: 6)
You can do it the same way that you would in C:
let randomNumber = arc4random()
randomNumber
is inferred to be of type UInt32
(a 32-bit unsigned integer)
rand
, arc4random
, drand48
and friends are all in the Darwin
module. It's already imported for you if you're building a Cocoa, UIKit, or Foundation app, but you'll need to import Darwin
in playgrounds.
Use arc4random_uniform()
Usage:
arc4random_uniform(someNumber: UInt32) -> UInt32
This gives you random integers in the range 0
to someNumber - 1
.
The maximum value for UInt32
is 4,294,967,295 (that is, 2^32 - 1
).
Examples:
Coin flip let flip = arc4random_uniform(2) // 0 or 1
Dice roll let roll = arc4random_uniform(6) + 1 // 1...6
Random day in October let day = arc4random_uniform(31) + 1 // 1...31
Random year in the 1990s let year = 1990 + arc4random_uniform(10)
General form:
let number = min + arc4random_uniform(max - min + 1)
where number
, max
, and min
are UInt32
.
What about...
arc4random()
You can also get a random number by using arc4random()
, which produces a UInt32
between 0 and 2^32-1. Thus to get a random number between 0
and x-1
, you can divide it by x
and take the remainder. Or in other words, use the Remainder Operator (%):
let number = arc4random() % 5 // 0...4
However, this produces the slight modulo bias (see also here and here), so that is why arc4random_uniform()
is recommended.
Converting to and from Int
Normally it would be fine to do something like this in order to convert back and forth between Int
and UInt32
:
let number: Int = 10
let random = Int(arc4random_uniform(UInt32(number)))
The problem, though, is that Int
has a range of -2,147,483,648...2,147,483,647
on 32 bit systems and a range of -9,223,372,036,854,775,808...9,223,372,036,854,775,807
on 64 bit systems. Compare this to the UInt32
range of 0...4,294,967,295
. The U
of UInt32
means unsigned.
Consider the following errors:
UInt32(-1) // negative numbers cause integer overflow error
UInt32(4294967296) // numbers greater than 4,294,967,295 cause integer overflow error
So you just need to be sure that your input parameters are within the UInt32
range and that you don't need an output that is outside of that range either.
Example for random number in between 10 (0-9);
import UIKit
let randomNumber = Int(arc4random_uniform(10))
Very easy code - simple and short.
I've been able to just use rand()
to get a random CInt. You can make it an Int by using something like this:
let myVar: Int = Int(rand())
You can use your favourite C random function, and just convert to value to Int if needed.
random()
, which returns an Int
rather than UInt32
-- and like @SomeGuy mentioned, simply call srandom(arc4random())
once anywhere before using it to ensure it has a different, randomized seed for each execution of your program.
@jstn's answer is good, but a bit verbose. Swift is known as a protocol-oriented language, so we can achieve the same result without having to implement boilerplate code for every class in the integer family, by adding a default implementation for the protocol extension.
public extension ExpressibleByIntegerLiteral {
public static func arc4random() -> Self {
var r: Self = 0
arc4random_buf(&r, MemoryLayout<Self>.size)
return r
}
}
Now we can do:
let i = Int.arc4random()
let j = UInt32.arc4random()
and all other integer classes are ok.
In Swift 4.2 you can generate random numbers by calling the random()
method on whatever numeric type you want, providing the range you want to work with. For example, this generates a random number in the range 1 through 9, inclusive on both sides
let randInt = Int.random(in: 1..<10)
Also with other types
let randFloat = Float.random(in: 1..<20)
let randDouble = Double.random(in: 1...30)
let randCGFloat = CGFloat.random(in: 1...40)
Updated: June 09, 2022.
Swift 5.7
Let's assume we have an array:
let numbers: [Int] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
For iOS and macOS you can use system-wide random source in Xcode's framework GameKit
. Here you can find GKRandomSource
class with its sharedRandom()
class method:
import GameKit
private func randomNumberGenerator() -> Int {
let rand = GKRandomSource.sharedRandom().nextInt(upperBound: numbers.count)
return numbers[rand]
}
randomNumberGenerator()
Also you can use a randomElement()
method that returns a random element of a collection:
let randomNumber = numbers.randomElement()!
print(randomNumber)
Or use arc4random_uniform()
. Pay attention that this method returns UInt32
type.
let generator = Int(arc4random_uniform(11))
print(generator)
And, of course, we can use a makeIterator()
method that returns an iterator over the elements of the collection.
let iterator: Int = (1...10).makeIterator().shuffled().first!
print(iterator)
The final example you see here returns a random value within the specified range with a help of static func random(in range: ClosedRange<Int>) -> Int
.
let randomizer = Int.random(in: 1...10)
print(randomizer)
Pseudo-random Double number generator drand48()
returns a value between 0.0 and 1.0.
import Foundation
let randomInt = Int(drand48() * 10)
Here is a library that does the job well https://github.com/thellimist/SwiftRandom
public extension Int {
/// SwiftRandom extension
public static func random(lower: Int = 0, _ upper: Int = 100) -> Int {
return lower + Int(arc4random_uniform(UInt32(upper - lower + 1)))
}
}
public extension Double {
/// SwiftRandom extension
public static func random(lower: Double = 0, _ upper: Double = 100) -> Double {
return (Double(arc4random()) / 0xFFFFFFFF) * (upper - lower) + lower
}
}
public extension Float {
/// SwiftRandom extension
public static func random(lower: Float = 0, _ upper: Float = 100) -> Float {
return (Float(arc4random()) / 0xFFFFFFFF) * (upper - lower) + lower
}
}
public extension CGFloat {
/// SwiftRandom extension
public static func random(lower: CGFloat = 0, _ upper: CGFloat = 1) -> CGFloat {
return CGFloat(Float(arc4random()) / Float(UINT32_MAX)) * (upper - lower) + lower
}
}
Since Swift 4.2
There is a new set of APIs:
let randomIntFrom0To10 = Int.random(in: 0 ..< 10)
let randomDouble = Double.random(in: 1 ... 10)
All numeric types now have the random(in:) method that takes range.
It returns a number uniformly distributed in that range.
TL;DR
Well, what is wrong with the "good" old way?
You have to use imported C APIs (They are different between platforms). And moreover...
What if I told you that the random is not that random?
If you use arc4random()
(to calculate the remainder) like arc4random() % aNumber
, the result is not uniformly distributed between the 0
and aNumber
. There is a problem called the Modulo bias.
Modulo bias
Normally, the function generates a random number between 0
and MAX (depends on the type etc.). To make a quick, easy example, let's say the max number is 7
and you care about a random number in the range 0 ..< 2
(or the interval [0, 3) if you prefer that).
The probabilities for individual numbers are:
0: 3/8 = 37.5%
1: 3/8 = 37.5%
2: 2/8 = 25%
In other words, you are more likely to end up with 0 or 1 than 2. Of course, bare in mind that this is extremely simplified and the MAX number is much higher, making it more "fair".
This problem is addressed by SE-0202 - Random unification in Swift 4.2
let MAX : UInt32 = 9
let MIN : UInt32 = 1
func randomNumber()
{
var random_number = Int(arc4random_uniform(MAX) + MIN)
print ("random = ", random_number);
}
I would like to add to existing answers that the random number generator example in the Swift book is a Linear Congruence Generator (LCG), it is a severely limited one and shouldn't be except for the must trivial examples, where quality of randomness doesn't matter at all. And a LCG should never be used for cryptographic purposes.
arc4random()
is much better and can be used for most purposes, but again should not be used for cryptographic purposes.
If you want something that is guaranteed to be cryptographically secure, use SecCopyRandomBytes()
. Note that if you build a random number generator into something, someone else might end up (mis)-using it for cryptographic purposes (such as password, key or salt generation), then you should consider using SecCopyRandomBytes()
anyway, even if your need doesn't quite require that.
Swift 4.2
Bye bye to import Foundation C lib arc4random_uniform()
// 1
let digit = Int.random(in: 0..<10)
// 2
if let anotherDigit = (0..<10).randomElement() {
print(anotherDigit)
} else {
print("Empty range.")
}
// 3
let double = Double.random(in: 0..<1)
let float = Float.random(in: 0..<1)
let cgFloat = CGFloat.random(in: 0..<1)
let bool = Bool.random()
You use random(in:) to generate random digits from ranges. randomElement() returns nil if the range is empty, so you unwrap the returned Int? with if let. You use random(in:) to generate a random Double, Float or CGFloat and random() to return a random Bool.
var randomNumber = Int(arc4random_uniform(UInt32(5)))
Here 5 will make sure that the random number is generated through zero to four. You can set the value accordingly.
Without arc4Random_uniform() in some versions of Xcode(in 7.1 it runs but doesn't autocomplete for me). You can do this instead.
To generate a random number from 0-5. First
import GameplayKit
Then
let diceRoll = GKRandomSource.sharedRandom().nextIntWithUpperBound(6)
The following code will produce a secure random number between 0 and 255:
extension UInt8 {
public static var random: UInt8 {
var number: UInt8 = 0
_ = SecRandomCopyBytes(kSecRandomDefault, 1, &number)
return number
}
}
You call it like this:
print(UInt8.random)
For bigger numbers it becomes more complicated. This is the best I could come up with:
extension UInt16 {
public static var random: UInt16 {
let count = Int(UInt8.random % 2) + 1
var numbers = [UInt8](repeating: 0, count: 2)
_ = SecRandomCopyBytes(kSecRandomDefault, count, &numbers)
return numbers.reversed().reduce(0) { $0 << 8 + UInt16($1) }
}
}
extension UInt32 {
public static var random: UInt32 {
let count = Int(UInt8.random % 4) + 1
var numbers = [UInt8](repeating: 0, count: 4)
_ = SecRandomCopyBytes(kSecRandomDefault, count, &numbers)
return numbers.reversed().reduce(0) { $0 << 8 + UInt32($1) }
}
}
These methods use an extra random number to determine how many UInt8
s are going to be used to create the random number. The last line converts the [UInt8]
to UInt16
or UInt32
.
I don't know if the last two still count as truly random, but you can tweak it to your likings :)
Swift 4.2
Swift 4.2 has included a native and fairly full-featured random number API in the standard library. (Swift Evolution proposal SE-0202)
let intBetween0to9 = Int.random(in: 0...9)
let doubleBetween0to1 = Double.random(in: 0...1)
All number types have the static random(in:) which takes the range and returns the random number in the given range
You can use GeneratorOf
like this:
var fibs = ArraySlice([1, 1])
var fibGenerator = GeneratorOf{
_ -> Int? in
fibs.append(fibs.reduce(0, combine:+))
return fibs.removeAtIndex(0)
}
println(fibGenerator.next())
println(fibGenerator.next())
println(fibGenerator.next())
println(fibGenerator.next())
println(fibGenerator.next())
println(fibGenerator.next())
I use this code to generate a random number:
//
// FactModel.swift
// Collection
//
// Created by Ahmadreza Shamimi on 6/11/16.
// Copyright © 2016 Ahmadreza Shamimi. All rights reserved.
//
import GameKit
struct FactModel {
let fun = ["I love swift","My name is Ahmadreza","I love coding" ,"I love PHP","My name is ALireza","I love Coding too"]
func getRandomNumber() -> String {
let randomNumber = GKRandomSource.sharedRandom().nextIntWithUpperBound(fun.count)
return fun[randomNumber]
}
}
Details
xCode 9.1, Swift 4
Math oriented solution (1)
import Foundation
class Random {
subscript<T>(_ min: T, _ max: T) -> T where T : BinaryInteger {
get {
return rand(min-1, max+1)
}
}
}
let rand = Random()
func rand<T>(_ min: T, _ max: T) -> T where T : BinaryInteger {
let _min = min + 1
let difference = max - _min
return T(arc4random_uniform(UInt32(difference))) + _min
}
Usage of solution (1)
let x = rand(-5, 5) // x = [-4, -3, -2, -1, 0, 1, 2, 3, 4]
let x = rand[0, 10] // x = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Programmers oriented solution (2)
Do not forget to add Math oriented solution (1) code here
import Foundation
extension CountableRange where Bound : BinaryInteger {
var random: Bound {
return rand(lowerBound-1, upperBound)
}
}
extension CountableClosedRange where Bound : BinaryInteger {
var random: Bound {
return rand[lowerBound, upperBound]
}
}
Usage of solution (2)
let x = (-8..<2).random // x = [-8, -7, -6, -5, -4, -3, -2, -1, 0, 1]
let x = (0..<10).random // x = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
let x = (-10 ... -2).random // x = [-10, -9, -8, -7, -6, -5, -4, -3, -2]
Full Sample
Do not forget to add solution (1) and solution (2) codes here
private func generateRandNums(closure:()->(Int)) {
var allNums = Set<Int>()
for _ in 0..<100 {
allNums.insert(closure())
}
print(allNums.sorted{ $0 < $1 })
}
generateRandNums {
(-8..<2).random
}
generateRandNums {
(0..<10).random
}
generateRandNums {
(-10 ... -2).random
}
generateRandNums {
rand(-5, 5)
}
generateRandNums {
rand[0, 10]
}
Sample result
https://i.stack.imgur.com/AlR58.png
Success story sharing