user5161989
user5161989

Reputation:

Generate random number of certain amount of digits

Hy,

I have a very Basic Question which is :

How can i create a random number with 20 digits no floats no negatives (basically an Int) in Swift ?

Thanks for all answers XD

Upvotes: 8

Views: 16663

Answers (8)

Mantas Laurinavičius
Mantas Laurinavičius

Reputation: 951

Usage in single extension:

Int.randomNumberWith(digits: 6) // 453532
extension Int {
    init(_ range: Range<Int> ) {
        let delta = range.startIndex < 0 ? abs(range.startIndex) : 0
        let min = UInt32(range.startIndex + delta)
        let max = UInt32(range.endIndex   + delta)
        self.init(Int(min + arc4random_uniform(max - min)) - delta)
    }
    
    static func randomNumberWith(digits: Int) -> Int {
        let min = Int(pow(Double(10), Double(digits-1))) - 1
        let max = Int(pow(Double(10), Double(digits))) - 1
        return Int(Range(uncheckedBounds: (min, max)))
    }
}

Upvotes: 0

Zafar Ahmad
Zafar Ahmad

Reputation: 3219

Swift 5: Simple Solution

func random(digits:Int) -> String {
    var number = String()
    for _ in 1...digits {
       number += "\(Int.random(in: 1...9))"
    }
    return number
}

print(random(digits: 1)) //3
print(random(digits: 2)) //59
print(random(digits: 3)) //926

Note It will return value in String, if you need Int value then you can do like this

let number = Int(random(digits: 1)) ?? 0

Upvotes: 15

Sombre Osmo&#39;z
Sombre Osmo&#39;z

Reputation: 175

Swift 4 version of Unome's validate response plus :

  • Guard it against overflow and 0 digit number

  • Adding support for Linux's device because "arc4random*" functions don't exit

With linux device don't forgot to do

#if os(Linux)
    srandom(UInt32(time(nil)))
#endif

only once before calling random.

/// This function generate a random number of type Int with the given digits number
///
/// - Parameter digit: the number of digit
/// - Returns: the ramdom generate number or nil if wrong parameter
func randomNumber(with digit: Int) -> Int? {

    guard 0 < digit, digit < 20 else { // 0 digit number don't exist and 20 digit Int are to big
        return nil
    }

    /// The final ramdom generate Int
    var finalNumber : Int = 0;

    for i in 1...digit {

        /// The new generated number which will be add to the final number
        var randomOperator : Int = 0

        repeat {
            #if os(Linux)
                randomOperator = Int(random() % 9) * Int(powf(10, Float(i - 1)))
            #else
                randomOperator = Int(arc4random_uniform(9)) * Int(powf(10, Float(i - 1)))
            #endif

        } while Double(randomOperator + finalNumber) > Double(Int.max) // Verification to be sure to don't overflow Int max size

        finalNumber += randomOperator
    }

    return finalNumber
} 

Upvotes: 1

FredFlinstone
FredFlinstone

Reputation: 956

Swift 3 appzyourlifz's answer updated to Swift 3

Step 1:

extension Int {
init(_ range: Range<Int> ) {
    let delta = range.lowerBound < 0 ? abs(range.lowerBound) : 0
    let min = UInt32(range.lowerBound + delta)
    let max = UInt32(range.upperBound   + delta)
    self.init(Int(min + arc4random_uniform(max - min)) - delta)
    }
}

Step 2:

func randomNumberWith(digits:Int) -> Int {
    let min = Int(pow(Double(10), Double(digits-1))) - 1
    let max = Int(pow(Double(10), Double(digits))) - 1
    return Int(Range(uncheckedBounds: (min, max)))
}

Usage:

randomNumberWith(digits:4) // 2271
randomNumberWith(digits:8) // 65273410 

Upvotes: 2

zaph
zaph

Reputation: 112855

Here is 18 decimal digits in a UInt64:

(Swift 3)

let sz: UInt32 = 1000000000
let ms: UInt64   = UInt64(arc4random_uniform(sz))
let ls: UInt64   = UInt64(arc4random_uniform(sz))
let digits: UInt64 = ms * UInt64(sz) + ls

print(String(format:"18 digits: %018llu", digits)) // Print with leading 0s.

16 decimal digits with leading digit 1..9 in a UInt64:

let sz: UInt64 = 100000000
let ld: UInt64 = UInt64(arc4random_uniform(9)+1)
let ms: UInt64 = UInt64(arc4random_uniform(UInt32(sz/10)))
let ls: UInt64 = UInt64(arc4random_uniform(UInt32(sz)))
let digits: UInt64 = ld * (sz*sz/10) + (ms * sz) + ls

print(String(format:"16 digits: %llu", digits))

Upvotes: 1

Mohammadalijf
Mohammadalijf

Reputation: 1377

you can create a string number then convert the number to your required number.

func generateRandomDigits(_ digitNumber: Int) -> String {
    var number = ""
    for i in 0..<digitNumber {
        var randomNumber = arc4random_uniform(10)
        while randomNumber == 0 && i == 0 {
            randomNumber = arc4random_uniform(10)
        }
        number += "\(randomNumber)"
    }
    return number
}

print(Int(generateRandomDigits(3)))

for 20 digit you can use Double instead of Int

Upvotes: 2

Luca Angeletti
Luca Angeletti

Reputation: 59526

Step 1

First of all we need an extension of Int to generate a random number in a range.

extension Int {
    init(_ range: Range<Int> ) {
        let delta = range.startIndex < 0 ? abs(range.startIndex) : 0
        let min = UInt32(range.startIndex + delta)
        let max = UInt32(range.endIndex   + delta)
        self.init(Int(min + arc4random_uniform(max - min)) - delta)
    }
}

This can be used this way:

Int(0...9) // 4 or 1 or 1...
Int(10...99) // 90 or 33 or 11
Int(100...999) // 200 or 333 or 893

Step 2

Now we need a function that receive the number of digits requested, calculates the range of the random number and finally does invoke the new initializer of Int.

func random(digits:Int) -> Int {
    let min = Int(pow(Double(10), Double(digits-1))) - 1
    let max = Int(pow(Double(10), Double(digits))) - 1
    return Int(min...max)
}

Test

random(1) // 8
random(2) // 12
random(3) // 829
random(4) // 2374

Upvotes: 16

Unome
Unome

Reputation: 6900

Here is some pseudocode that should do what you want.

generateRandomNumber(20)
func generateRandomNumber(int numDigits){
   var place = 1
   var finalNumber = 0;
   for(int i = 0; i < numDigits; i++){
      place *= 10
      var randomNumber = arc4random_uniform(10)
      finalNumber += randomNumber * place
  }
  return finalNumber
}

Its pretty simple. You generate 20 random numbers, and multiply them by the respective tens, hundredths, thousands... place that they should be on. This way you will guarantee a number of the correct size, but will randomly generate the number that will be used in each place.

Update

As said in the comments you will most likely get an overflow exception with a number this long, so you'll have to be creative in how you'd like to store the number (String, ect...) but I merely wanted to show you a simple way to generate a number with a guaranteed digit length. Also, given the current code there is a small chance your leading number could be 0 so you should protect against that as well.

Upvotes: 4

Related Questions