How Does One Generate a Random Number in Swift

How does one generate a random number in Swift?

Swift 4.2+

Swift 4.2 shipped with Xcode 10 introduces new easy-to-use random functions for many data types.
You can 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()

Generating random numbers with Swift

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

How to Generate a New Random Number Once Every time Content View Loads?

Approach #1:

MyView is created once, when ContentView renders.

Inside MyView, randomInt is set when the view is first created and then never modified. When you press the button, myMessage is set, but randomInt is never changed. If you wanted randomInt to change, you'd want to say something like:

randomInt = Int.random(in: 1...100)

inside your button action:

Approach #2:

You're creating a new randomInt variable in the local scope by declaring let randomInt = inside the view body.

Instead, if I'm reading your initial question correctly, I think you'd want something using onAppear:

struct MyView: View {

@State var randomInt = 0
@State var myMessage: String = ""

var body: some View {
VStack {
Text(String(randomInt))

Button("Press Me") {
myMessage = String(randomInt)
}

Text(myMessage)
}.onAppear {
randomInt = Int.random(in: 1...100)
}
}
}

You'll see that with this, every time you go back in the navigation hierarchy and then revisit MyView, there's a new value (since it appears again). The button triggering a re-render doesn't re-trigger onAppear

Approach #3:

MyView gets created on the first render of the parent view (ContentView). Unless something triggers a refresh of ContentView, you wouldn't generate a new random number here.


In conclusion, I'm a little unclear on what the initial requirement is (what does it mean for a View to 'load'? Does this just mean when it gets shown on the screen?), but hopefully this describes each scenario and maybe introduces the idea of onAppear, which seems like it might be what you're looking for.


Addendum: if you want the random number to be generated only when ContentView loads (as the title says), I'd create it in ContentView instead of your MyView and pass it as a parameter.


struct ContentView: View {
@State var randomInt = Int.random(in: 1...100)

var body: some View {

NavigationView {

NavigationLink(destination: MyView(randomInt: $randomInt)) {
Text("Link to MyView")
}
}
}
}

struct MyView: View {

@Binding var randomInt : Int
@State var myMessage: String = ""

var body: some View {

Text(String(randomInt))

Button("Press me to refresh only myMessage") {
myMessage = String(randomInt)
}

Button("Press me to change the randomInt as well") {
randomInt = Int.random(in: 1...100)
myMessage = String(randomInt)
}

Text(myMessage)
}

}

How to generate a random number in Swift without repeating the previous random number?

Store the previous generated number in a variable and compare the generated number to the previous number. If they match generate a new random number. Repeat the generation of new numbers until they don't match.

var previousNumber: UInt32? // used in randomNumber() 

func randomNumber() -> UInt32 {
var randomNumber = arc4random_uniform(10)
while previousNumber == randomNumber {
randomNumber = arc4random_uniform(10)
}
previousNumber = randomNumber
return randomNumber
}

How to generate different random number in a range in Swift?

A Set is simpler, it guarantees unique values

var randomIndex = Set<Int>()

while randomIndex.count < 3 {
randomIndex.insert(Int.random(in: 1 ... 10))
}

Another approach is to create an array of the values, pick a random element and remove this element from the array

var randomValues = Set<Int>()
var valueArray = Array(1...10)
for _ in 0..<3 {
guard let randomElement = valueArray.randomElement() else { break }
randomValues.insert(randomElement)
valueArray.remove(at: valueArray.firstIndex(of: randomElement)!)
}

Regarding is there any way to optimize my approach the for loop in your code is extremely expensive.

First of all the recommended syntax for an index based loop is

for i in 0 ..< generatedValue.count {

But actually you don't need the index so Fast Enumeration is better

for value in generatedValue {
if randomValue != value {

The most expensive part of the loop is that the entire array is always iterated even if the value was already found. At least add a break statement to exit the loop

for value in generatedValue {
if randomValue != value {
randomIndex.append(randomValue)
c += 1
break
}
}

But there is still a more efficient syntax

if !generatedValue.contains(randomValue) {
randomIndex.append(randomValue)
c += 1
}

Generating a random number in Swift

It really depends on how much casting you want to avoid. You could simply wrap it in a function:

func random(max maxNumber: Int) -> Int {
return Int(arc4random_uniform(UInt32(maxNumber)))
}

So then you only have to do the ugly casting once. Everywhere you want a random number with a maximum number:

let r = random(max: _names.count)
let name: String = _names[r]

As a side note, since this is Swift, your properties don't need _ in front of them.

How do I generate a random number not including one without using a while loop?

Updated for Swift 5.1

Excluding 1 value

var nums = [Int](1...100)
nums.remove(at: 42)

let random = Int(arc4random_uniform(UInt32(nums.count)))
print(nums[random])

Excluding multiple values

This extension of Range does provide a solution when you want to exclude more than 1 value.

extension ClosedRange where Element: Hashable {
func random(without excluded:[Element]) -> Element {
let valid = Set(self).subtracting(Set(excluded))
let random = Int(arc4random_uniform(UInt32(valid.count)))
return Array(valid)[random]
}
}

Example

(1...100).random(without: [40,50,60])

I believe the computation complexity of this second solution is O(n) where n is the number of elements included in the range.

The assumption here is the no more than n excluded values are provided by the caller.

Generating random values in Swift between two integer values

try this

let randomNumber = arc4random_uniform(40) + 10
println(randomNumber)

in general form

let lower : UInt32 = 10
let upper : UInt32 = 50
let randomNumber = arc4random_uniform(upper - lower) + lower
println(randomNumber)

How do you generate a random number in swift?

The random number generator you created is not truly random, it's psueodorandom.

With a psuedorandom random number generator, the sequence depends on the seed. Change the seed, you change the sequence.

One common usage is to set the seed as the current time, which usually makes it random enough.

You can also use the standard libraries: arc4random(). Don't forget to import Foundation.



Related Topics



Leave a reply



Submit