How does one generate a random number in Apple's Swift language?

后端 未结 25 1602
有刺的猬
有刺的猬 2020-11-22 09:51

I realize the Swift book provided an implementation of a random number generator. Is the best practice to copy and paste this implementation in one\'s own program? Or is t

相关标签:
25条回答
  • 2020-11-22 10:21

    Since Swift 4.2

    There is a new set of APIs:

    let randomIntFrom0To10 = Int.random(in: 0 ..< 10)
    let randomDouble = Double.random(in: 1 ... 10)
    
    • All numeric types now have the random(in:) method that takes range.

    • It returns a number uniformly distributed in that range.


    TL;DR

    Well, what is wrong with the "good" old way?

    1. You have to use imported C APIs (They are different between platforms).

    2. And moreover...

    What if I told you that the random is not that random?

    If you use arc4random() (to calculate the remainder) like arc4random() % aNumber, the result is not uniformly distributed between the 0 and aNumber. There is a problem called the Modulo bias.

    Modulo bias

    Normally, the function generates a random number between 0 and MAX (depends on the type etc.). To make a quick, easy example, let's say the max number is 7 and you care about a random number in the range 0 ..< 2 (or the interval [0, 3) if you prefer that).

    The probabilities for individual numbers are:

    • 0: 3/8 = 37.5%
    • 1: 3/8 = 37.5%
    • 2: 2/8 = 25%

    In other words, you are more likely to end up with 0 or 1 than 2. Of course, bare in mind that this is extremely simplified and the MAX number is much higher, making it more "fair".

    This problem is addressed by SE-0202 - Random unification in Swift 4.2

    0 讨论(0)
  • 2020-11-22 10:22

    I've been able to just use rand() to get a random CInt. You can make it an Int by using something like this:

    let myVar: Int = Int(rand())
    

    You can use your favourite C random function, and just convert to value to Int if needed.

    0 讨论(0)
  • 2020-11-22 10:23

    I use this code to generate a random number:

    //
    //  FactModel.swift
    //  Collection
    //
    //  Created by Ahmadreza Shamimi on 6/11/16.
    //  Copyright © 2016 Ahmadreza Shamimi. All rights reserved.
    //
    
    import GameKit
    
    struct FactModel {
    
        let fun  = ["I love swift","My name is Ahmadreza","I love coding" ,"I love PHP","My name is ALireza","I love Coding too"]
    
    
        func getRandomNumber() -> String {
    
            let randomNumber  = GKRandomSource.sharedRandom().nextIntWithUpperBound(fun.count)
    
            return fun[randomNumber]
        }
    }
    
    0 讨论(0)
  • 2020-11-22 10:26

    Use arc4random_uniform()

    Usage:

    arc4random_uniform(someNumber: UInt32) -> UInt32

    This gives you random integers in the range 0 to someNumber - 1.

    The maximum value for UInt32 is 4,294,967,295 (that is, 2^32 - 1).

    Examples:

    • Coin flip

        let flip = arc4random_uniform(2) // 0 or 1
      
    • Dice roll

        let roll = arc4random_uniform(6) + 1 // 1...6
      
    • Random day in October

        let day = arc4random_uniform(31) + 1 // 1...31
      
    • Random year in the 1990s

        let year = 1990 + arc4random_uniform(10)
      

    General form:

    let number = min + arc4random_uniform(max - min + 1)
    

    where number, max, and min are UInt32.

    What about...

    arc4random()

    You can also get a random number by using arc4random(), which produces a UInt32 between 0 and 2^32-1. Thus to get a random number between 0 and x-1, you can divide it by x and take the remainder. Or in other words, use the Remainder Operator (%):

    let number = arc4random() % 5 // 0...4
    

    However, this produces the slight modulo bias (see also here and here), so that is why arc4random_uniform() is recommended.

    Converting to and from Int

    Normally it would be fine to do something like this in order to convert back and forth between Int and UInt32:

    let number: Int = 10
    let random = Int(arc4random_uniform(UInt32(number)))
    

    The problem, though, is that Int has a range of -2,147,483,648...2,147,483,647 on 32 bit systems and a range of -9,223,372,036,854,775,808...9,223,372,036,854,775,807 on 64 bit systems. Compare this to the UInt32 range of 0...4,294,967,295. The U of UInt32 means unsigned.

    Consider the following errors:

    UInt32(-1) // negative numbers cause integer overflow error
    UInt32(4294967296) // numbers greater than 4,294,967,295 cause integer overflow error
    

    So you just need to be sure that your input parameters are within the UInt32 range and that you don't need an output that is outside of that range either.

    0 讨论(0)
  • 2020-11-22 10:26
    var randomNumber = Int(arc4random_uniform(UInt32(5)))
    

    Here 5 will make sure that the random number is generated through zero to four. You can set the value accordingly.

    0 讨论(0)
  • 2020-11-22 10:27

    I used this code:

    var k: Int = random() % 10;
    
    0 讨论(0)
提交回复
热议问题