使用Swift生成随机数

95

我需要生成一个随机数。

看起来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”)使其可用。 - Vince O'Sullivan
概率 = Int(arc4random_uniform(UInt32(total))) - 因为类型提示已经损坏,打字的投诉不具体,这是来自两个不同错误的转换投诉。 - bshirley
16个回答

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

Float.random() is currently marked Beta, and so gives 'Float' has no member 'random' - Dale

23

你也可以尝试:

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

我不得不添加"UInt32"才能使它工作。


1
当我查找此函数时,我看到public func arc4random_uniform(_: UInt32) -> UInt32。所以我想知道为什么要将参数转换为UInt32?这里是否还发生了其他事情? - Mark Moeykens

8

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

例如,像 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)) } - Cortado-J

5

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

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)

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()的函数,该函数从/dev/urandom读取UInt64,则可以像这样使用它:
let rand = xorshift128plus(urand64(), urand64())
for _ in 1...10 {
    print(rand())
}

1

我作为一个整数扩展的实现。将在范围 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
另一个选项是使用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)

以下示例取自苹果的示例代码:https://github.com/carekit-apple/CareKit/blob/master/CareKitPrototypingTool/OCKPrototyper/CareKitPatient/RandomNumberGeneratorHelper.swift


1
这是我如何在两个整数之间获取随机数的方法!
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
let MAX : UInt32 = 9
let MIN : UInt32 = 1 
func randomNumber()
{
   var random_number = Int(arc4random_uniform(MAX) + MIN)
   print ("random = ", random_number);    
}

为什么你不提供这段代码的解释呢? - reformed

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接