How to express 64-bit integers in Swift? - swift

I'm doing an exercise which requires producing 64-bit positive integers in Swfit, but I have no idea how that can be achieved. My machine is 64-bit for sure, but my test code cannot even produce 63-bit prositive integers.
Using Double may solve the problem, but that's not what the exercise intends to be. Is there any solution for this issue? Thank you.
The test code is as follows:
import Foundation
func numberOfGrainsOnChessBoard () {
let ar = Array(1...64)
let arr = ar.map{twoMultipliedNTimes($0)}
var index = 1
for i in arr {
print("\(index): \(i)")
index = index + 1
}
}
func twoMultipliedNTimes (_ times: Int) -> UInt64 {
var product : UInt64 = 1;
for _ in 1...times {
product = product * 2
}
return product
}
addGrainsOnChessBoard()
The above code got an overflown error.

The code below will generate random Int64 bits integers between it's minimum and it's maximum value. So you can change the range to fit your needs.
let myInt: Int64 = Int64.random(in: Int64.min...Int64.max)

Related

Why I cannot update my custom UInt64 Var to maximum capacity in a mathematical func?

I am trying calculate 2^64 with my custom-pow function.
So far I built 2 versions of it. Version 2 works.
I think version 1 should also work, but Swift crashes with an overflow error. I think It must work because I am "not" loading a higher number than I'm allowed! Why it is happening?
Version 1.0.0
func powV1(number: Int8, power: Int8) -> UInt64 {
var returnValue: UInt64 = 1
for _ in 1 ... power {
returnValue = returnValue * UInt64(number)
}
return returnValue
}
Version 2.0.0
func powV2(number: Int8, power: Int8) -> Decimal {
var returnValue: Decimal = 1
for _ in 1 ... power {
returnValue = returnValue * Decimal(number)
}
return returnValue
}
And here is call site:
powV1(number: 2, power: 64) // ← Error: OverFlow
PS: Everyone is very welcome to improve version 2.0.0
Update:
func powV1_0_1(number: Int8, power: Int8) -> UInt64 {
var returnValue: UInt64 = 1
for i in 1 ... power {
if i == power && power == 64
{
let last = Decimal(returnValue)*Decimal(number) - 1
returnValue = UInt64(last) // Error: Decimal should conform BinaryInteger says Error!?!
}
else
{
returnValue = returnValue*UInt64(number)
}
}
return returnValue
}
The problem is that the max value UInt64 can hold is 2^64-1, not 2^64, so 2^64 rightly overflows a UInt64.
Moreover, your function takes signed integers, whose powers can result in negative numbers, so returning a UInt64 is a bad idea. Or if you really want a UInt64, you should ensure the inputs can't produce a negative output (if number is negative, power should be an even number).

Swift: find out how many digits an integer has

I don't have the right English or math vocabulary to really explain what I want to do, but I'll try to explain. Basically I want to figure out "how big" an integer is, how many decimal positions it has. For example 1234 is "a thousand" number, and 2,987,123 is "a million" number.
I can do something like this, but that is rather silly :)
extension Int {
func size() -> Int {
switch self {
case 0...99:
return 10
case 100...999:
return 100
case 1000...9999:
return 1000
case 10000...99999:
return 10000
case 100000...999999:
return 100000
case 1000000...9999999:
return 1000000
default:
return 0 // where do we stop?
}
}
}
A solution using logarithms:
Note: This solution has limitations due to the inability of Double to fully represent the log10 of large Int converted to Double. It starts failing around 15
digits for Ints very close to the next power of 10 (e.g.
999999999999999).
This is a problem:
log10(Double(999999999999999)) == log10(Double(1000000000000000))
extension Int {
var size: Int {
self == 0 ? 1 : Int(pow(10.0, floor(log10(abs(Double(self))))))
}
}
A solution using Strings:
It avoids any mathematical representation errors by working entirely with Int and String.
extension Int {
var size: Int {
Int("1" + repeatElement("0", count: String(self.magnitude).count - 1))!
}
}
A generic version for any FixedWidthInteger:
In collaboration with #LeoDabus, I present the generic version for any integer type:
extension FixedWidthInteger {
var size: Self {
Self("1" + repeatElement("0", count: String(self.magnitude).count - 1))!
}
}
Examples:
Int8.max.size // 100
Int16.max.size // 10000
Int32.max.size // 1000000000
Int.max.size // 1000000000000000000
UInt.max.size // 10000000000000000000
I came up with this:
extension Int {
func size() -> Int {
var size = 1
var modifyingNumber = self
while modifyingNumber > 10 {
modifyingNumber = modifyingNumber / 10
size = size * 10
}
return size
}
}
Works, but it's rather imperative.
Is this too silly?
extension Int {
var size : Int {
String(self).count
}
}
My reasoning is that a "digit" really is a manner of writing, so converting to String answers the real question. Converting the size back to a number (i.e. the corresponding power of ten) would then of course lead right back to the logarithm answer. :)

Swift - Efficient Number to Character Conversion

If I have a long range of numbers such as 1...1000000, what would be an efficient way to convert them to strings with the following mapping?
1->A, 2->B, 3->C, ... 10->A0, 11->AA, 12->AB etc.
I took the approach of splitting each number into digits (using modulus) and using it to get a character from an array to build the strings. Takes about 5 seconds for 1...1000. Is there a faster approach?
My code:
let numbers = 1...1000000
let charArray:[Character] = ["0","A","B","C","D","E","F","G","H","I"]
var results: [String] = []
func transformNumbers() {
for number in numbers {
var string = ""
var i = number
while i > 0 {string.insert(charArray[(i%10)], at: string.startIndex); i/=10}
results.append(string)
}
}
Your code took about 15 seconds on my old MacBook for 1...1000000, and the code below, less than 1 second:
(Using Xcode 8.3.3 with Release build on macOS 10.12.5)
let unicodeScalarArray:[UnicodeScalar] = ["0","A","B","C","D","E","F","G","H","I"]
let utf16CodeUnitArray:[UInt16] = unicodeScalarArray.map{UInt16($0.value)}
var results: [String] = []
func transformNumbers7() {
results = numbers.map {number in
var digits: [UInt16] = []
var i = number
while i > 0 {digits.append(utf16CodeUnitArray[i%10]); i/=10}
digits.reverse()
return String(utf16CodeUnits: digits, count: digits.count)
}
}
Generally,
Repeated insert(_:at:) can be slower than repeated append(_:) and reverse()
Working with Characters may be less efficient than UnicodeScalar, UTF-16 Code Units or UTF-8 Code Units.
Not sure if it is the fastest way, but switching to a map expression instead of mutating the results list speeds things up a bit over 10x on my machine:
let results = numbers.map { (val: Int) -> String in
var string = ""
var i = val
while i > 0 {string.insert(charArray[(i%10)], at: string.startIndex); i/=10}
return string
}

Generating random numbers with Swift

I need to generate a random number.
It appears the arc4random function no longer exists as well as the arc4random_uniform function.
The options I have are arc4random_stir(), arc4random_buf(UnsafeMutablePointer<Void>, Int), and arc4random_addrandom(UnsafeMutablePointer<UInt8>, Int32).
I can't find any docs on the functions and no comments in the header files give hints.
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()
You could try as well:
let diceRoll = Int(arc4random_uniform(UInt32(6)))
I had to add "UInt32" to make it work.
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.
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)
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 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);
}
In Swift 3 :
It will generate random number between 0 to limit
let limit : UInt32 = 6
print("Random Number : \(arc4random_uniform(limit))")
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))
}
}
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))")
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]
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)))]
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.
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
}
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

How to generate a random number in Swift?

I realize the Swift book provided an implementation of a random number generator. Is the best practice to copy and paste this implementation? Or is there a library that does this that we can use now?
Swift 4.2+
Swift 4.2 shipped with Xcode 10 introduces new easy-to-use random functions for many data types.
You simply call the random() method on numeric types.
let randomInt = Int.random(in: 0..<6)
let randomDouble = Double.random(in: 2.71828...3.14159)
let randomBool = Bool.random()
Use arc4random_uniform(n) for a random integer between 0 and n-1.
let diceRoll = Int(arc4random_uniform(6) + 1)
Cast the result to Int so you don't have to explicitly type your vars as UInt32 (which seems un-Swifty).
Edit: Updated for Swift 3.0
arc4random works well in Swift, but the base functions are limited to 32-bit integer types (Int is 64-bit on iPhone 5S and modern Macs). Here's a generic function for a random number of a type expressible by an integer literal:
public func arc4random<T: ExpressibleByIntegerLiteral>(_ type: T.Type) -> T {
var r: T = 0
arc4random_buf(&r, MemoryLayout<T>.size)
return r
}
We can use this new generic function to extend UInt64, adding boundary arguments and mitigating modulo bias. (This is lifted straight from arc4random.c)
public extension UInt64 {
public static func random(lower: UInt64 = min, upper: UInt64 = max) -> UInt64 {
var m: UInt64
let u = upper - lower
var r = arc4random(UInt64.self)
if u > UInt64(Int64.max) {
m = 1 + ~u
} else {
m = ((max - (u * 2)) + 1) % u
}
while r < m {
r = arc4random(UInt64.self)
}
return (r % u) + lower
}
}
With that we can extend Int64 for the same arguments, dealing with overflow:
public extension Int64 {
public static func random(lower: Int64 = min, upper: Int64 = max) -> Int64 {
let (s, overflow) = Int64.subtractWithOverflow(upper, lower)
let u = overflow ? UInt64.max - UInt64(~s) : UInt64(s)
let r = UInt64.random(upper: u)
if r > UInt64(Int64.max) {
return Int64(r - (UInt64(~lower) + 1))
} else {
return Int64(r) + lower
}
}
}
To complete the family...
private let _wordSize = __WORDSIZE
public extension UInt32 {
public static func random(lower: UInt32 = min, upper: UInt32 = max) -> UInt32 {
return arc4random_uniform(upper - lower) + lower
}
}
public extension Int32 {
public static func random(lower: Int32 = min, upper: Int32 = max) -> Int32 {
let r = arc4random_uniform(UInt32(Int64(upper) - Int64(lower)))
return Int32(Int64(r) + Int64(lower))
}
}
public extension UInt {
public static func random(lower: UInt = min, upper: UInt = max) -> UInt {
switch (_wordSize) {
case 32: return UInt(UInt32.random(UInt32(lower), upper: UInt32(upper)))
case 64: return UInt(UInt64.random(UInt64(lower), upper: UInt64(upper)))
default: return lower
}
}
}
public extension Int {
public static func random(lower: Int = min, upper: Int = max) -> Int {
switch (_wordSize) {
case 32: return Int(Int32.random(Int32(lower), upper: Int32(upper)))
case 64: return Int(Int64.random(Int64(lower), upper: Int64(upper)))
default: return lower
}
}
}
After all that, we can finally do something like this:
let diceRoll = UInt64.random(lower: 1, upper: 7)
Edit for Swift 4.2
Starting in Swift 4.2, instead of using the imported C function arc4random_uniform(), you can now use Swift’s own native functions.
// Generates integers starting with 0 up to, and including, 10
Int.random(in: 0 ... 10)
You can use random(in:) to get random values for other primitive values as well; such as Int, Double, Float and even Bool.
Swift versions < 4.2
This method will generate a random Int value between the given minimum and maximum
func randomInt(min: Int, max: Int) -> Int {
return min + Int(arc4random_uniform(UInt32(max - min + 1)))
}
I used this code:
var k: Int = random() % 10;
As of iOS 9, you can use the new GameplayKit classes to generate random numbers in a variety of ways.
You have four source types to choose from: a general random source (unnamed, down to the system to choose what it does), linear congruential, ARC4 and Mersenne Twister. These can generate random ints, floats and bools.
At the simplest level, you can generate a random number from the system's built-in random source like this:
GKRandomSource.sharedRandom().nextInt()
That generates a number between -2,147,483,648 and 2,147,483,647. If you want a number between 0 and an upper bound (exclusive) you'd use this:
GKRandomSource.sharedRandom().nextIntWithUpperBound(6)
GameplayKit has some convenience constructors built in to work with dice. For example, you can roll a six-sided die like this:
let d6 = GKRandomDistribution.d6()
d6.nextInt()
Plus you can shape the random distribution by using things like GKShuffledDistribution. That takes a little more explaining, but if you're interested you can read my tutorial on GameplayKit random numbers.
You can do it the same way that you would in C:
let randomNumber = arc4random()
randomNumber is inferred to be of type UInt32 (a 32-bit unsigned integer)
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.
Example for random number in between 10 (0-9);
import UIKit
let randomNumber = Int(arc4random_uniform(10))
Very easy code - simple and short.
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.
#jstn's answer is good, but a bit verbose. Swift is known as a protocol-oriented language, so we can achieve the same result without having to implement boilerplate code for every class in the integer family, by adding a default implementation for the protocol extension.
public extension ExpressibleByIntegerLiteral {
public static func arc4random() -> Self {
var r: Self = 0
arc4random_buf(&r, MemoryLayout<Self>.size)
return r
}
}
Now we can do:
let i = Int.arc4random()
let j = UInt32.arc4random()
and all other integer classes are ok.
Updated: June 09, 2022.
Swift 5.7
Let's assume we have an array:
let numbers: [Int] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
For iOS and macOS you can use system-wide random source in Xcode's framework GameKit. Here you can find GKRandomSource class with its sharedRandom() class method:
import GameKit
private func randomNumberGenerator() -> Int {
let rand = GKRandomSource.sharedRandom().nextInt(upperBound: numbers.count)
return numbers[rand]
}
randomNumberGenerator()
Also you can use a randomElement() method that returns a random element of a collection:
let randomNumber = numbers.randomElement()!
print(randomNumber)
Or use arc4random_uniform(). Pay attention that this method returns UInt32 type.
let generator = Int(arc4random_uniform(11))
print(generator)
And, of course, we can use a makeIterator() method that returns an iterator over the elements of the collection.
let iterator: Int = (1...10).makeIterator().shuffled().first!
print(iterator)
The final example you see here returns a random value within the specified range with a help of static func random(in range: ClosedRange<Int>) -> Int.
let randomizer = Int.random(in: 1...10)
print(randomizer)
Pseudo-random Double number generator drand48() returns a value between 0.0 and 1.0.
import Foundation
let randomInt = Int(drand48() * 10)
In Swift 4.2 you can generate random numbers by calling the random() method on whatever numeric type you want, providing the range you want to work with. For example, this generates a random number in the range 1 through 9, inclusive on both sides
let randInt = Int.random(in: 1..<10)
Also with other types
let randFloat = Float.random(in: 1..<20)
let randDouble = Double.random(in: 1...30)
let randCGFloat = CGFloat.random(in: 1...40)
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?
You have to use imported C APIs (They are different between platforms).
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
Here is a library that does the job well
https://github.com/thellimist/SwiftRandom
public extension Int {
/// SwiftRandom extension
public static func random(lower: Int = 0, _ upper: Int = 100) -> Int {
return lower + Int(arc4random_uniform(UInt32(upper - lower + 1)))
}
}
public extension Double {
/// SwiftRandom extension
public static func random(lower: Double = 0, _ upper: Double = 100) -> Double {
return (Double(arc4random()) / 0xFFFFFFFF) * (upper - lower) + lower
}
}
public extension Float {
/// SwiftRandom extension
public static func random(lower: Float = 0, _ upper: Float = 100) -> Float {
return (Float(arc4random()) / 0xFFFFFFFF) * (upper - lower) + lower
}
}
public extension CGFloat {
/// SwiftRandom extension
public static func random(lower: CGFloat = 0, _ upper: CGFloat = 1) -> CGFloat {
return CGFloat(Float(arc4random()) / Float(UINT32_MAX)) * (upper - lower) + lower
}
}
let MAX : UInt32 = 9
let MIN : UInt32 = 1
func randomNumber()
{
var random_number = Int(arc4random_uniform(MAX) + MIN)
print ("random = ", random_number);
}
I would like to add to existing answers that the random number generator example in the Swift book is a Linear Congruence Generator (LCG), it is a severely limited one and shouldn't be except for the must trivial examples, where quality of randomness doesn't matter at all. And a LCG should never be used for cryptographic purposes.
arc4random() is much better and can be used for most purposes, but again should not be used for cryptographic purposes.
If you want something that is guaranteed to be cryptographically secure, use SecCopyRandomBytes(). Note that if you build a random number generator into something, someone else might end up (mis)-using it for cryptographic purposes (such as password, key or salt generation), then you should consider using SecCopyRandomBytes() anyway, even if your need doesn't quite require that.
Swift 4.2
Bye bye to import Foundation C lib arc4random_uniform()
// 1
let digit = Int.random(in: 0..<10)
// 2
if let anotherDigit = (0..<10).randomElement() {
print(anotherDigit)
} else {
print("Empty range.")
}
// 3
let double = Double.random(in: 0..<1)
let float = Float.random(in: 0..<1)
let cgFloat = CGFloat.random(in: 0..<1)
let bool = Bool.random()
You use random(in:) to generate random digits from ranges.
randomElement() returns nil if the range is empty, so you unwrap the returned Int? with if let.
You use random(in:) to generate a random Double, Float or CGFloat and random() to return a random Bool.
More # Official
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.
Without arc4Random_uniform() in some versions of Xcode(in 7.1 it runs but doesn't autocomplete for me). You can do this instead.
To generate a random number from 0-5.
First
import GameplayKit
Then
let diceRoll = GKRandomSource.sharedRandom().nextIntWithUpperBound(6)
The following code will produce a secure random number between 0 and 255:
extension UInt8 {
public static var random: UInt8 {
var number: UInt8 = 0
_ = SecRandomCopyBytes(kSecRandomDefault, 1, &number)
return number
}
}
You call it like this:
print(UInt8.random)
For bigger numbers it becomes more complicated.
This is the best I could come up with:
extension UInt16 {
public static var random: UInt16 {
let count = Int(UInt8.random % 2) + 1
var numbers = [UInt8](repeating: 0, count: 2)
_ = SecRandomCopyBytes(kSecRandomDefault, count, &numbers)
return numbers.reversed().reduce(0) { $0 << 8 + UInt16($1) }
}
}
extension UInt32 {
public static var random: UInt32 {
let count = Int(UInt8.random % 4) + 1
var numbers = [UInt8](repeating: 0, count: 4)
_ = SecRandomCopyBytes(kSecRandomDefault, count, &numbers)
return numbers.reversed().reduce(0) { $0 << 8 + UInt32($1) }
}
}
These methods use an extra random number to determine how many UInt8s are going to be used to create the random number. The last line converts the [UInt8] to UInt16 or UInt32.
I don't know if the last two still count as truly random, but you can tweak it to your likings :)
Swift 4.2
Swift 4.2 has included a native and fairly full-featured random number API in the standard library. (Swift Evolution proposal SE-0202)
let intBetween0to9 = Int.random(in: 0...9)
let doubleBetween0to1 = Double.random(in: 0...1)
All number types have the static random(in:) which takes the range and returns the random number in the given range
Xcode 14, swift 5
public extension Array where Element == Int {
static func generateNonRepeatedRandom(size: Int) -> [Int] {
guard size > 0 else {
return [Int]()
}
return Array(0..<size).shuffled()
}
}
How to use:
let array = Array.generateNonRepeatedRandom(size: 15)
print(array)
Output
You can use GeneratorOf like this:
var fibs = ArraySlice([1, 1])
var fibGenerator = GeneratorOf{
_ -> Int? in
fibs.append(fibs.reduce(0, combine:+))
return fibs.removeAtIndex(0)
}
println(fibGenerator.next())
println(fibGenerator.next())
println(fibGenerator.next())
println(fibGenerator.next())
println(fibGenerator.next())
println(fibGenerator.next())
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]
}
}
Details
xCode 9.1, Swift 4
Math oriented solution (1)
import Foundation
class Random {
subscript<T>(_ min: T, _ max: T) -> T where T : BinaryInteger {
get {
return rand(min-1, max+1)
}
}
}
let rand = Random()
func rand<T>(_ min: T, _ max: T) -> T where T : BinaryInteger {
let _min = min + 1
let difference = max - _min
return T(arc4random_uniform(UInt32(difference))) + _min
}
Usage of solution (1)
let x = rand(-5, 5) // x = [-4, -3, -2, -1, 0, 1, 2, 3, 4]
let x = rand[0, 10] // x = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Programmers oriented solution (2)
Do not forget to add Math oriented solution (1) code here
import Foundation
extension CountableRange where Bound : BinaryInteger {
var random: Bound {
return rand(lowerBound-1, upperBound)
}
}
extension CountableClosedRange where Bound : BinaryInteger {
var random: Bound {
return rand[lowerBound, upperBound]
}
}
Usage of solution (2)
let x = (-8..<2).random // x = [-8, -7, -6, -5, -4, -3, -2, -1, 0, 1]
let x = (0..<10).random // x = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
let x = (-10 ... -2).random // x = [-10, -9, -8, -7, -6, -5, -4, -3, -2]
Full Sample
Do not forget to add solution (1) and solution (2) codes here
private func generateRandNums(closure:()->(Int)) {
var allNums = Set<Int>()
for _ in 0..<100 {
allNums.insert(closure())
}
print(allNums.sorted{ $0 < $1 })
}
generateRandNums {
(-8..<2).random
}
generateRandNums {
(0..<10).random
}
generateRandNums {
(-10 ... -2).random
}
generateRandNums {
rand(-5, 5)
}
generateRandNums {
rand[0, 10]
}
Sample result