用 Swift 生成随机数

我需要生成一个随机数。

看来 arc4random函数和 arc4random_uniform函数都不复存在了。

我的选项是 arc4random_stir()arc4random_buf(UnsafeMutablePointer<Void>, Int)arc4random_addrandom(UnsafeMutablePointer<UInt8>, Int32)

我找不到关于函数的任何文档,头文件中也没有提示。

125778 次浏览
let randomIntFrom0To10 = Int.random(in: 1..<10)
let randomFloat = Float.random(in: 0..<1)


// if you want to get a random element in an array
let greetings = ["hey", "hi", "hello", "hola"]
greetings.randomElement()

look, i had the same problem but i insert the function as a global variable

as

var RNumber = Int(arc4random_uniform(9)+1)


func GetCase(){


your code
}

obviously this is not efficent, so then i just copy and paste the code into the function so it could be reusable, then xcode suggest me to set the var as constant so my code were

func GetCase() {


let RNumber = Int(arc4random_uniform(9)+1)


if categoria == 1 {
}
}

well thats a part of my code so xcode tell me something of inmutable and initialization but, it build the app anyway and that advice simply dissapear

hope it helps

You could try as well:

let diceRoll = Int(arc4random_uniform(UInt32(6)))

I had to add "UInt32" to make it work.

After some investigation I wrote this:

import Foundation


struct Math {
private static var seeded = false


static func randomFractional() -> CGFloat {


if !Math.seeded {
let time = Int(NSDate().timeIntervalSinceReferenceDate)
srand48(time)
Math.seeded = true
}


return CGFloat(drand48())
}
}

Now you can just do Math.randomFraction() to get random numbers [0..1[ without having to remember seeding first. Hope this helps someone :o)

Another option is to use the xorshift128plus algorithm:

func xorshift128plus(seed0 : UInt64, _ seed1 : UInt64) -> () -> UInt64 {
var state0 : UInt64 = seed0
var state1 : UInt64 = seed1
if state0 == 0 && state1 == 0 {
state0 = 1 // both state variables cannot be 0
}


func rand() -> UInt64 {
var s1 : UInt64 = state0
let s0 : UInt64 = state1
state0 = s0
s1 ^= s1 << 23
s1 ^= s1 >> 17
s1 ^= s0
s1 ^= s0 >> 26
state1 = s1
return UInt64.addWithOverflow(state0, state1).0
}


return rand
}

This algorithm has a period of 2^128 - 1 and passes all the tests of the BigCrush test suite. Note that while this is a high-quality pseudo-random number generator with a long period, it is not a cryptographically secure random number generator.

You could seed it from the current time or any other random source of entropy. For example, if you had a function called urand64() that read a UInt64 from /dev/urandom, you could use it like this:

let rand = xorshift128plus(urand64(), urand64())
for _ in 1...10 {
print(rand())
}
let MAX : UInt32 = 9
let MIN : UInt32 = 1
func randomNumber()
{
var random_number = Int(arc4random_uniform(MAX) + MIN)
print ("random = ", random_number);
}

you can use this in specific rate:

let die = [1, 2, 3, 4, 5, 6]
let firstRoll = die[Int(arc4random_uniform(UInt32(die.count)))]
let secondRoll = die[Int(arc4random_uniform(UInt32(die.count)))]

Just call this function and provide minimum and maximum range of number and you will get a random number.

eg.like randomNumber(MIN: 0, MAX: 10) and You will get number between 0 to 9.

func randomNumber(MIN: Int, MAX: Int)-> Int{
return Int(arc4random_uniform(UInt32(MAX-MIN)) + UInt32(MIN));
}

Note:- You will always get output an Integer number.

In Swift 3 :

It will generate random number between 0 to limit

let limit : UInt32 = 6
print("Random Number : \(arc4random_uniform(limit))")

Lets Code with Swift for the random number or random string :)

let quotes: NSArray = ["R", "A", "N", "D", "O", "M"]


let randomNumber = arc4random_uniform(UInt32(quotes.count))
let quoteString = quotes[Int(randomNumber)]
print(quoteString)

it will give you output randomly.

My implementation as an Int extension. Will generate random numbers in range from..<to

public extension Int {
static func random(from: Int, to: Int) -> Int {
guard to > from else {
assertionFailure("Can not generate negative random numbers")
return 0
}
return Int(arc4random_uniform(UInt32(to - from)) + UInt32(from))
}
}

Don't forget that some numbers will repeat! so you need to do something like....

my totalQuestions was 47.

func getRandomNumbers(totalQuestions:Int) -> NSMutableArray
{


var arrayOfRandomQuestions: [Int] = []


print("arraySizeRequired = 40")
print("totalQuestions = \(totalQuestions)")


//This will output a 40 random numbers between 0 and totalQuestions (47)
while arrayOfRandomQuestions.count < 40
{


let limit: UInt32 = UInt32(totalQuestions)


let theRandomNumber = (Int(arc4random_uniform(limit)))


if arrayOfRandomQuestions.contains(theRandomNumber)
{
print("ping")


}
else
{
//item not found
arrayOfRandomQuestions.append(theRandomNumber)
}


}


print("Random Number set = \(arrayOfRandomQuestions)")
print("arrayOutputCount = \(arrayOfRandomQuestions.count)")




return arrayOfRandomQuestions as! NSMutableArray


}

This is how I get a random number between 2 int's!

func randomNumber(MIN: Int, MAX: Int)-> Int{
var list : [Int] = []
for i in MIN...MAX {
list.append(i)
}
return list[Int(arc4random_uniform(UInt32(list.count)))]
}

usage:

print("My Random Number is: \(randomNumber(MIN:-10,MAX:10))")

Update with swift 4.2 :

let randomInt = Int.random(in: 1..<5)
let randomFloat = Float.random(in: 1..<10)
let randomDouble = Double.random(in: 1...100)
let randomCGFloat = CGFloat.random(in: 1...1000)

Another option is to use GKMersenneTwisterRandomSource from GameKit. The docs say:

A deterministic pseudo-random source that generates random numbers based on a mersenne twister algorithm. This is a deterministic random source suitable for creating reliable gameplay mechanics. It is slightly slower than an Arc4 source, but more random, in that it has a longer period until repeating sequences. While deterministic, this is not a cryptographic random source. It is however suitable for obfuscation of gameplay data.

import GameKit


let minValue = 0
let maxValue = 100


var randomDistribution: GKRandomDistribution?
let randomSource = GKMersenneTwisterRandomSource()
randomDistribution = GKRandomDistribution(randomSource: randomSource, lowestValue: minValue, highestValue: maxValue)
let number = randomDistribution?.nextInt() ?? 0
print(number)

Example taken from Apple's sample code: https://github.com/carekit-apple/CareKit/blob/master/CareKitPrototypingTool/OCKPrototyper/CareKitPatient/RandomNumberGeneratorHelper.swift

I'm late to the party 🤩🎉

Using a function that allows you to change the size of the array and the range selection on the fly is the most versatile method. You can also use map so it's very concise. I use it in all of my performance testing/bench marking.

elements is the number of items in the array
only including numbers from 0...max

func randArr(_ elements: Int, _ max: Int) -> [Int] {
return (0..<elements).map{ _ in Int.random(in: 0...max) }
}

Code Sense / Placeholders look like this. randArr(elements: Int, max: Int)

10 elements in my array ranging from 0 to 1000.

randArr(10, 1000) // [554, 8, 54, 87, 10, 33, 349, 888, 2, 77]