How does one make random number between range for arc4random_uniform()?

RangeSwiftArc4random

Range Problem Overview


so my goal in this codebit is to randomly roll two dice and as we all know your regular die only has 6 sides so I imported Foundation for access to arc4random_uniform(UInt32). I attempted using the range of (1..7) to avoid randomly getting 0 however that returned an error which I didn't enjoy too much. I tried to do this:

dice1 = arc4random_uniform(UInt32(1..7))

however that returned

> Could not find an overload for 'init' that accepts the supplied arguments

I hope that this is enough information for you amazing debs out there to help me :)

Please note I am just doing this in a playground to practice swift. It isn't imperative that I learn how to do this; it's just me tinkering before I jump into building actual apps :D

//imports random number function
import Foundation
//creates data storage for dice roll
var dice1: UInt32 = 0
var dice2: UInt32 = 0
//counter variable
var i = 0
//how many times snake eyes happens
var snakeeyes = 0
 //how many times a double is rolled
var `double` = 0
//rolls dice 100 times
while i < 100{
    //from here
    //sets dice roll

This returns an error of 'Range $T3' is not convertible to UInt32

> dice1 = arc4random_uniform(1..7) > dice2 = arc4random_uniform(1..7)

    //checks for snake eyes
    if dice1 == 1 && dice2 == 1 {
        snakeeyes = snakeeyes + 1
    
    }
    //checks for doubles
    if dice1 == dice2{
        `double` = `double` + 1
    }
    //increases counter
        i = i + 1
    //to here
}
println("You got Snake Eyes \(snakeeyes) times.")
println("You got Doubles, \(`double`) times.")

Range Solutions


Solution 1 - Range

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;

Solution 2 - Range

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

Solution 3 - Range

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.

Solution 4 - Range

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

Solution 5 - Range

If You want i create that for random numbers. this is extension of number Int and Double, Float

/**
    Arc Random for Double and Float
*/
public func arc4random <T: IntegerLiteralConvertible> (type: T.Type) -> T {
    var r: T = 0
    arc4random_buf(&r, UInt(sizeof(T)))
    return r
}
public extension Int {
    /**
    Create a random num Int
    :param: lower number Int
    :param: upper number Int
    :return: random number Int
    By DaRkDOG
    */
    public static func random (#lower: Int , upper: Int) -> Int {
        return lower + Int(arc4random_uniform(upper - lower + 1))
    }
    
}
public extension Double {
    /**
    Create a random num Double
    :param: lower number Double
    :param: upper number Double
    :return: random number Double
    By DaRkDOG
    */
    public static func random(#lower: Double, upper: Double) -> Double {
        let r = Double(arc4random(UInt64)) / Double(UInt64.max)
        return (r * (upper - lower)) + lower
    }
}
public extension Float {
    /**
    Create a random num Float
    :param: lower number Float
    :param: upper number Float
    :return: random number Float
    By DaRkDOG
    */
    public static func random(#lower: Float, upper: Float) -> Float {
        let r = Float(arc4random(UInt32)) / Float(UInt32.max)
        return (r * (upper - lower)) + lower
    }
}

USE :

let randomNumDouble = Double.random(lower: 0.00, upper: 23.50)
let randomNumInt = Int.random(lower: 56, upper: 992)
let randomNumInt =Float.random(lower: 6.98, upper: 923.09)

Solution 6 - Range

Swift 3/4:

func randomNumber(range: ClosedRange<Int> = 1...6) -> Int {
    let min = range.lowerBound
    let max = range.upperBound
    return Int(arc4random_uniform(UInt32(1 + max - min))) + min
}

Solution 7 - Range

That's because arc4random_uniform() is defined as follows:

func arc4random_uniform(_: UInt32) -> UInt32

It takes a UInt32 as input, and spits out a UInt32. You're attempting to pass it a range of values. arc4random_uniform gives you a random number in between 0 and and the number you pass it (exclusively), so if for example, you wanted to find a random number between -50 and 50, as in [-50, 50] you could use arc4random_uniform(101) - 50

Solution 8 - Range

I modified @DaRk-_-D0G's answer to work with Swift 2.0

/**
Arc Random for Double and Float
*/
public func arc4random <T: IntegerLiteralConvertible> (type: T.Type) -> T {
	var r: T = 0
	arc4random_buf(&r, sizeof(T))
	return r
}
public extension Int {
	/**
	Create a random num Int
	:param: lower number Int
	:param: upper number Int
	:return: random number Int
	By DaRkDOG
	*/
	public static func random (lower: Int , upper: Int) -> Int {
		return lower + Int(arc4random_uniform(UInt32(upper - lower + 1)))
	}
	
}
public extension Double {
	/**
	Create a random num Double
	:param: lower number Double
	:param: upper number Double
	:return: random number Double
	By DaRkDOG
	*/
	public static func random(lower: Double, upper: Double) -> Double {
		let r = Double(arc4random(UInt64)) / Double(UInt64.max)
		return (r * (upper - lower)) + lower
	}
}
public extension Float {
	/**
	Create a random num Float
	:param: lower number Float
	:param: upper number Float
	:return: random number Float
	By DaRkDOG
	*/
	public static func random(lower: Float, upper: Float) -> Float {
		let r = Float(arc4random(UInt32)) / Float(UInt32.max)
		return (r * (upper - lower)) + lower
	}
}

Solution 9 - Range

Swift:

var index = 1 + random() % 6

Solution 10 - Range

In swift...

This is inclusive, calling random(1,2) will return a 1 or a 2, This will also work with negative numbers.

	func random(min: Int, _ max: Int) -> Int {
		guard min < max else {return min}
		return Int(arc4random_uniform(UInt32(1 + max - min))) + min
	}

Solution 11 - Range

The answer is just 1 line code:

let randomNumber = arc4random_uniform(8999) + 1000 //for 4 digit random number
let randomNumber = arc4random_uniform(899999999) + 100000000 //for 9 digit random number
let randomNumber = arc4random_uniform(89) + 10    //for 2 digit random number
let randomNumber = arc4random_uniform(899) + 100  //for 3 digit random number

The alternate solution is:

    func generateRandomNumber(numDigits: Int) -> Int{
    var place = 1
    var finalNumber = 0;
    var finanum = 0;
    for var i in 0 ..< numDigits {
        place *= 10
        let randomNumber = arc4random_uniform(10)         
        finalNumber += Int(randomNumber) * place
        finanum = finalNumber / 10
           i += 1
    }
    return finanum
}

Although the drawback is that number cannot start from 0.

Solution 12 - Range

Edit: Swift 4.2+ provides this now:

(100...200).randomElement()

It’s idiomatic to me to extend Range:

public extension Range where Bound == Int {
    var random: Int {
        return lowerBound + Int(arc4random_uniform(UInt32(upperBound - lowerBound)))
    }
}

public extension ClosedRange where Bound == Int {
    var random: Int {
        return lowerBound + Int(arc4random_uniform(UInt32(upperBound - lowerBound + 1)))
    }
}

In use:

let foo = (100..<600).random

Solution 13 - Range

Since Swift 4.2:

Int {    
    public static func random(in range: ClosedRange<Int>) -> Int
    public static func random(in range: Range<Int>) -> Int
}

Used like:

Int.random(in: 2...10)

Solution 14 - Range

I successfully accomplished creating a random number using the following code:

var coin = arc4random_uniform(2) + 1

Hope this can help you.

Solution 15 - Range

Swift 3 Xcode Beta 5 Solution. Based on Ted van Gaalen Answer.

extension Int
  {
     static func random(range: Range<Int> ) -> Int
    {
        var offset = 0
        
        if range.lowerBound < 0   // allow negative ranges
        {
            offset = Swift.abs(range.lowerBound)
        }
        
        let mini = UInt32(range.lowerBound + offset)
        let maxi = UInt32(range.upperBound   + offset)
        
        return Int(mini + arc4random_uniform(maxi - mini)) - offset
    }
}

Solution 16 - Range

var rangeFromLimits = arc4random_uniform( (UPPerBound - LOWerBound) + 1)) + LOWerBound;

Solution 17 - Range

hope this is working. make random number between range for arc4random_uniform()?

var randomNumber = Int(arc4random_uniform(6))
print(randomNumber)

Solution 18 - Range

Probably one find useful this a bit updated version of Range extension from Ted van Gaalen's answer using Swift 4/Xcode 9+:

extension CountableClosedRange where Bound == Int {
    var randomFromRange: Bound {
        get {
            var offset = 0
            if lowerBound < 0 {
                offset = abs(lowerBound)
            }
            let mini = UInt32(lowerBound + offset)
            let maxi = UInt32(upperBound + offset)
            return Int(mini + arc4random_uniform(maxi - mini)) - offset
        }
    }
}

let n = (-1000 ... 1000).randomFromRange
print(n)

Or this a bit "hacky" solution to support open and closed intervals:

extension CountableRange where Bound == Int {
    var randomFromRange: Bound {
        return uniformRandom(from: lowerBound, to: upperBound)
    }
}

extension CountableClosedRange where Bound == Int {
    var randomFromRange: Bound {
        return uniformRandom(from: lowerBound, to: upperBound - 1)
    }
}

func uniformRandom(from: Int, to: Int) -> Int {
    var offset = 0
    if from < 0 {
        offset = abs(from)
    }
    let mini = UInt32(from + offset)
    let maxi = UInt32(to + offset)
    return Int(mini + arc4random_uniform(maxi - mini)) - offset
}

Not sure if there is a way to add property to both types of intervals simultaneously.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionarcreighView Question on Stackoverflow
Solution 1 - RangeSkyView Answer on Stackoverflow
Solution 2 - RangeTed van GaalenView Answer on Stackoverflow
Solution 3 - RangeAshView Answer on Stackoverflow
Solution 4 - RangeNosov PavelView Answer on Stackoverflow
Solution 5 - RangeYannStephView Answer on Stackoverflow
Solution 6 - RangeAlessandro OrnanoView Answer on Stackoverflow
Solution 7 - RangeMick MacCallumView Answer on Stackoverflow
Solution 8 - RangeJopedView Answer on Stackoverflow
Solution 9 - RangeAlexander VolkovView Answer on Stackoverflow
Solution 10 - RangeCarter MedlinView Answer on Stackoverflow
Solution 11 - RangeNupur SharmaView Answer on Stackoverflow
Solution 12 - RangemxclView Answer on Stackoverflow
Solution 13 - RangeCamsoftView Answer on Stackoverflow
Solution 14 - RangeBigfoot11View Answer on Stackoverflow
Solution 15 - RangeStatikView Answer on Stackoverflow
Solution 16 - RangeAsim KhanView Answer on Stackoverflow
Solution 17 - RangeVidhyapathi KandhasamyView Answer on Stackoverflow
Solution 18 - RangedevforfuView Answer on Stackoverflow