How does one make random number between range for arc4random_uniform()?
Quite a few good answers, but I just wanted to share my personal favourite Swift random number generation function for positive integers:
Swift 2
func randomNumber(range: Range<Int> = 1...6) -> Int {
let min = range.startIndex
let max = range.endIndex
return Int(arc4random_uniform(UInt32(max - min))) + min
}
Swift 3
Here's a quick update for Swift 3 and, as a bonus, it now works for any value type that conforms to the SignedInteger protocol - much more convenient for core data applications that need to specify Int16, Int32 etc. As a quick note, if you really need it to work on unsigned integers as well, just copy the entire function then replace SignedInteger
with UnsignedInteger
and toIntMax()
with toUIntMax()
.
func randomNumber<T : SignedInteger>(inRange range: ClosedRange<T> = 1...6) -> T {
let length = (range.upperBound - range.lowerBound + 1).toIntMax()
let value = arc4random().toIntMax() % length + range.lowerBound.toIntMax()
return T(value)
}
Swift 4
Thanks to the removal of toIntMax() in Swift 4, we now have to use a different means of converting to a common integer type. In this example I'm using Int64 which is large enough for my purposes, but if you're using unsigned integers or have an Int128 or Int256 custom type you should use those.
public func randomNumber<T : SignedInteger>(inRange range: ClosedRange<T> = 1...6) -> T {
let length = Int64(range.upperBound - range.lowerBound + 1)
let value = Int64(arc4random()) % length + Int64(range.lowerBound)
return T(value)
}
One more, for the total random-phile, here's an extension that returns a random element from any Collection
type object. Note this uses the above function to generate its index so you will need both.
extension Collection {
func randomItem() -> Self.Iterator.Element {
let count = distance(from: startIndex, to: endIndex)
let roll = randomNumber(inRange: 0...count-1)
return self[index(startIndex, offsetBy: roll)]
}
}
Usage
randomNumber()
returns a random number between 1 and 6.
randomNumber(50...100)
returns a number between 50 and 100 inclusive. Naturally you can replace the values of 50 and 100 with whatever you like.
Swift 4.2
Alas, my best StackOverflow answer has been rendered obsolete at last. You can now use simply Int.random(in: 1 ... 6)
to generate a random number in a given range. Also works for other forms of integer and floating point number. Collection types also now provide shuffle()
and randomElement()
functions. There is therefore no longer any need for fancy randomisation functions unless you want to use a specific randomiser type.
I believe you should do
dice1 = arc4random_uniform(6) + 1;
to get the range 1 - 6. I don't do iOS objective C nor have I any knowledge on swift-language though. The random method should return a value between 0 and 5, and + 1 will make it a value between 1 and 6.
If you need a range between lets say 10 - 30 then just do
int random = arc4random_uniform(21) + 10;
According to Swift 4.2 now it's easily to get random number like this
let randomDouble = Double.random(in: -7.9...12.8)
let randomIntFrom0To10 = Int.random(in: 0 ..< 10)
for more details check this out
I've made an Int type extension. tested it in playground, hope this is useful. It also accepts negative ranges:
extension Int
{
static func random(range: Range<Int> ) -> Int
{
var offset = 0
if range.startIndex < 0 // allow negative ranges
{
offset = abs(range.startIndex)
}
let mini = UInt32(range.startIndex + offset)
let maxi = UInt32(range.endIndex + offset)
return Int(mini + arc4random_uniform(maxi - mini)) - offset
}
}
use like
var aRandomInt = Int.random(-500...100) // returns a random number within the given range.
or define it as a Range extension as property like this:
extension Range
{
var randomInt: Int
{
get
{
var offset = 0
if (startIndex as Int) < 0 // allow negative ranges
{
offset = abs(startIndex as Int)
}
let mini = UInt32(startIndex as Int + offset)
let maxi = UInt32(endIndex as Int + offset)
return Int(mini + arc4random_uniform(maxi - mini)) - offset
}
}
}
// usage example: get an Int within the given Range:
let nr = (-1000 ... 1100).randomInt