使用Swift生成随机数


92

我需要生成一个随机数。

似乎该arc4random功能以及该arc4random_uniform功能不再存在。

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

我在函数上找不到任何文档,头文件中也没有注释。


3
看来Xcode中的自动完成功能刚刚中断。我可能发誓我没有自动完成就键入了它,而且它没有编译。现在工作。@arsen的不错参考
Big_Mac

1
arc4random_uniform可用。它是Foundation API的一部分,而不是语言的本机部分,因此您需要在文件的开头添加“ import Foundation”(或“ import UIKit”)以使其可用。
文斯·奥沙利文

概率= Int(arc4random_uniform(UInt32(total)))–因为提前输入已损坏,所以打字投诉不是特定的,那是我的演员投诉来自两个不同的错误
bshirley

Answers:


227

===== Swift 4.2 / Xcode 10 =====

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()

斯威夫特在引擎盖下arc4random_buf用来完成工作。

===== Swift 4.1 / Xcode 9 =====

arc4random()返回04294967295之间的随机数

drand48()返回0.01.0范围内的随机数

arc4random_uniform(N)返回0N-1范围内的随机数

例子:

arc4random() // => UInt32 = 2739058784
arc4random() // => UInt32 = 2672503239
arc4random() // => UInt32 = 3990537167
arc4random() // => UInt32 = 2516511476
arc4random() // => UInt32 = 3959558840

drand48() // => Double = 0.88642843322303122
drand48() // => Double = 0.015582849408328769
drand48() // => Double = 0.58409022031727176
drand48() // => Double = 0.15936862653180484
drand48() // => Double = 0.38371587480719427

arc4random_uniform(3) // => UInt32 = 0
arc4random_uniform(3) // => UInt32 = 1
arc4random_uniform(3) // => UInt32 = 0
arc4random_uniform(3) // => UInt32 = 1
arc4random_uniform(3) // => UInt32 = 2

建议在诸如此类的结构上使用arc4random_uniform(),arc4random() % upper_bound因为当上限不是2的幂时,它会避免“模偏差”。


Float.random()当前标记为Beta,因此给出'Float' has no member 'random'
Dale

22

您也可以尝试:

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

我必须添加“ UInt32”以使其工作。


1
当我查找此功能时,我看到了public func arc4random_uniform(_: UInt32) -> UInt32。所以我想知道为什么将参数转换为UInt32?这里还有其他事吗?
Mark Moeykens '16

8

只需调用此函数并提供最小和最大范围的数字,您将获得一个随机数。

例如like randomNumber(MIN:0,MAX:10),您将获得介于0到9之间的数字。

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

注意:-您将始终获得输出整数。


1
我认为需要: func randomNumber(MIN: Int, MAX: Int)-> Int{ return Int(arc4random_uniform(UInt32(MAX-MIN)) + UInt32(MIN)); }
Adahus

5

经过一番调查,我写道:

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())
   }
}

现在,您只需Math.randomFraction()获取随机数[0..1 [,而不必先记住种子即可。希望这可以帮助某人:o)


4

用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)

3

另一个选择是使用xorshift128plus算法:

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
}

该算法的周期为2 ^ 128-1,并通过了BigCrush测试套件的所有测试。请注意,虽然这是一个具有较长时间的高质量伪随机数生成器,但它不是密码安全的随机数生成器

您可以从当前时间或任何其他随机熵源中播种它。例如,如果您有一个名为从urand64()读取的函数,则可以这样使用它:UInt64/dev/urandom

let rand = xorshift128plus(urand64(), urand64())
for _ in 1...10 {
    print(rand())
}

1
let MAX : UInt32 = 9
let MIN : UInt32 = 1 
func randomNumber()
{
   var random_number = Int(arc4random_uniform(MAX) + MIN)
   print ("random = ", random_number);    
}

您为什么不提供此代码的说明?
进行了改革

1

在Swift 3中:

它将生成0到限制之间的随机数

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

如果我想生成5到10的随机数,而不是0到n的随机数
Rishi,

1
@Rishi从5点到10点将是arc4random_uniform(6) + 5
Matt Le

1

我的实现为Int扩展。将生成范围内的随机数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))
    }
}

1

这就是我如何获得2个整数之间的随机数!

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)))]
}

用法:

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

1

另一个选择是使用GameKit中的GKMersenneTwisterRandomSource。文档说:

确定性伪随机源,它基于mersenne twister算法生成随机数。这是确定性随机源,适用于创建可靠的游戏机制。它比Arc4来源慢一点,但更随机,因为它有更长的时间直到重复序列。虽然是确定性的,但这不是加密随机源。但是,它适用于混淆游戏数据。

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)

摘自Apple的示例代码的示例:https : //github.com/carekit-apple/CareKit/blob/master/CareKitPrototypingTool/OCKPrototyper/CareKitPatient/RandomNumberGeneratorHelper.swift


1

我参加聚会迟到了

使用允许您即时更改数组大小和范围选择的功能是最通用的方法。您也可以使用地图,因此非常简洁。我在所有性能测试/基准测试中都使用了它。

elements是数组中的项目数,
仅包括来自0...max

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

代码感知/占位符看起来像这样。 randArr(elements: Int, max: Int)

我数组中的10个元素,范围从0到1000。

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

0

您可以按特定的比率使用它:

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)))]

0

让我们用Swift编写随机数或随机字符串的代码:)

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

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

它将给您随机输出。


0

不要忘记一些数字会重复!所以您需要做类似...的事情。

我的总问题是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

}

-2

看,我有同样的问题,但是我将函数作为全局变量插入

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

func GetCase(){

your code
}

显然,这没有效果,所以我只是将代码复制并粘贴到函数中,以便可以重复使用,然后xcode建议我将var设置为常量,这样我的代码就可以了

func GetCase() {

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

   if categoria == 1 {
    }
}

嗯,这就是我的代码的一部分,所以xcode告诉我一些不可变和初始化的内容,但是无论如何,它都会构建应用程序,而该建议却消失了

希望能帮助到你

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.