Summary of the use of random numbers in Swift

Summary of the use of random numbers in Swift

In the process of development, we need to generate some random numbers from time to time. Here we summarize some common random number generation functions in Swift. Here we will make some examples in Playground.

Integer random number

If we want an integer random number, we can consider using the arc4random series of functions. We can use the man arc4random command to look at the definition of this function:

The arc4random() function uses the key stream generator employed by the arc4 cipher, which uses 8*8 8 bit S-Boxes. The S-Boxes can be inabout (21700) states. The arc4random() function returns pseudo-random numbers in the range of 0 to (232)-1, and therefore has twice the range of rand(3) and random(3).

arc4random uses the arc4 cryptographically encrypted key stream generator (please use your imagination) to generate a random number in the interval [0, 2^32) (note that it is a left-closed and right-open interval). The return type of this function is UInt32. As shown below:

  1. arc4random() // 2,919,646,954  

If we want to generate an integer random number within a specified range, we can use arc4random() % upper_bound, where upper_bound specifies the upper bound, as follows:

  1. arc4random() % 10   // 8  

However, when using this method, when upper_bound is not a power of 2, a so-called Modulo bias problem will occur.

We can view the arc4random documentation through the man arc4random command in the console, and there is such a line:

arc4random_uniform() will return a uniformly distributed random number less than upper_bound. arc4random_uniform() is recommended over constructions like ''arc4random() % upper_bound'' as it avoids “modulo bias” when the upper bound is not a power of two.

Therefore, arc4random_uniform can be used, which accepts a parameter of type UInt32 to specify the upper boundary of the random number interval upper_bound. The random number range generated by this function is [0, upper_bound), as shown below:

  1. arc4random_uniform( 10 ) // 6  

If you want to specify the minimum value of the interval (such as the random number interval is [5, 100)), you can do it as follows:

  1. let max: UInt32 = 100  
  2. let min: UInt32 = 5  
  3. arc4random_uniform(max - min) + min // 82  

Of course, you can also use the traditional C functions rand and random in Swift. However, these two functions have the following disadvantages:

Both functions require an initial seed, usually determined by the current time.

The upper limit of these two functions is RAND_MAX=0X7fffffff(2147483647), which is half of arc4random.

The rand function is implemented in a regular low-order loop, which is easier to predict.

Let's take rand as an example and see how it is used:

  1. srand(UInt32(time(nil))) // seed, random corresponds to srandom  
  2. rand() // 1,314,695,483  
  3. rand() % 10   // 8  

64-bit integer random number

In most applications, the functions mentioned above are sufficient to meet our needs for obtaining integer random numbers. However, if we look at their function declarations, we can find that these functions are mainly used for 32-bit integer operations. What if we need to generate a 64-bit integer random number? After all, new machines now support 64-bit integers.

There seems to be no existing function to generate 64-bit random numbers, but jstn shared his method with us on stackoverflow. Let's take a look.

He first defines a generic function as follows:

  1. func arc4random (type: T.Type) -> T {
  2. var r: T = 0  
  3. arc4random_buf(&r, UInt(sizeof(T)))
  4. return r
  5. }

This function uses arc4random_buf to generate random numbers. Let's look at the definition of this function through man arc4random_buf:

arc4random_buf() function fills the region buf of length nbytes with ARC4-derived random data.

This function uses ARC4 encrypted random numbers to fill the buffer area of ​​the length specified by the second parameter of the function. Therefore, if we pass in sizeof(UInt64), the function will generate a random number to fill the 8-byte area and return it to r. Then the 64-bit random number generation method can be implemented as follows:

  1. extension UInt64 {
  2. static func random(lower: UInt64 = min, upper: UInt64 = max) -> UInt64 {
  3. var m: UInt64
  4. let u = upper - lower
  5. var r = arc4random(UInt64)
  6. if u > UInt64(Int64.max) {
  7. m = 1 + ~u
  8. } else {
  9. m = ((max - (u * 2 )) + 1 ) % u
  10. }
  11. while r < m {
  12. r = arc4random(UInt64)
  13. }
  14. return (r % u) + lower
  15. }
  16. }

Let's try it out:

  1. UInt64.random() // 4758246381445086013  

Of course, jstn also provides the implementation of Int64, UInt32, and Int32, so you can use your imagination to find out.

Floating point random number

If you need a random floating point value, you can use the drand48 function, which generates a floating point number in the range [0.0, 1.0]. The return value of this function is Double type. Its usage is as follows:

  1. srand48(Int(time(nil)))
  2. drand48() // 0.396464773760275  

Remember that this function needs to call srand48 first to generate an initial seed value.

A small example

I recently wrote a random keyboard that needs to sort the numbers 0-9 randomly, and I just used the arc4random function above, as shown below:

  1. let arr = [ "0" , "1" , "2" , "3" , "4" , "5" , "6" , "7" , "8" , "9" ]
  2. let numbers = arr.sort { (_, _) -> Bool in
  3. arc4random() < arc4random()
  4. }

In the closure, two numbers are randomly generated and compared to determine the sorting rules of the array. It's pretty simple.

summary

In fact, if you look at the API of C functions in Swift, you will find that there are many functions related to random numbers, such as arc4random_addrandom, erand48, etc. The above are just some of the functions we often use, and these functions are basically enough. Of course, different scenarios have different requirements, and we need to choose the appropriate function according to the actual needs.

The above code has been uploaded to github. The address is Random.playground. You can refer to it if you need it.

<<:  A brief discussion on the core of the program - complexity

>>:  When HR asks you "Anything else you want to ask?", what's the best way to answer?

Recommend

A guide to gaining followers through short videos!

Today I’m sharing with you a “Short Video Fan Exp...

Foxconn begins to come to the fore. What kind of game is Terry Gou playing?

Since Foxconn acquired Sharp, every decision made...

Carcinogenic? Loss of nutrients? Air fryers are in trouble...

◎ Comprehensive report by Wang Yu of Science and ...

Three barriers to adoption of Tesla's home battery

Tesla CEO Elon Musk just unveiled a line of home ...

Form costs reduced by 30%, home decoration advertising case!

With the further deepening of regulation and cont...

Tencent Advertising Guide for the Dental Industry

1. Oral Industry Research 1. Overview of the dent...

Want to start a business? Answer these 6 questions first

[[155511]] I often meet entrepreneurs who have gr...

The changes are huge? What are the changes in Android 5.0?

Less than a year after the last major update of t...

66 tactics for brand marketing planning!

Nouns must have roots; adjectives are strong imag...