Search code examples
xcoderandomswiftarc4random

Swift random number problems


I am using Swift with Xcode 6 Beta 5, and trying to generate a random number between my specific constraints.

Currently I am using the arc4random_uniform() function, which works for simple generating like:

arc4random_uniform(5)

But I am trying to create a random number with some complicated boundaries. This is my attempt:

randomMovement = Int( arc4random_uniform( (0.25 * Int(cs)) - ( 0.175 * rd ) ) ) + Int( 0.175 * rd )

cs and rd are both integers - initially, cs = 100, and rd = 40. This should generate a random number between 7 and 25. However, I run into many problems in Xcode with this, due to the variable types.

With this code, it initially shows the one error - On the first '*', it says:

'Int' is not convertible to 'UInt8'

But when I change that, it comes up with more problems, and it seems like I keep going round in a circle.

What's going wrong, and how can i fix this?


Solution

  • When you have type problems, build up your expression step by step.

    import Darwin
    
    let cs = 100
    let rd = 40
    
    let min = UInt32(0.175 * Float(rd))
    let max = UInt32(0.25 * Float(cs))
    
    // This isn't really necessary, the next line will crash if it's not true, but
    // just calling out this implicit assumption
    assert(max >= min)
    
    let randomMovement = Int(arc4random_uniform(max - min) + min)
    

    arc4random_uniform takes a UInt32, so you need to get there. You can't multiply Float and Int without a typecast, so you need to add those.

    When I say "build up step-by-step" I mean for you, not the compiler. The compiler can handle:

    let randomMovement = Int(arc4random_uniform(UInt32(0.25 * Float(cs)) - UInt32(0.175 * Float(rd))) + UInt32(0.25 * Float(cs)))
    

    but it's a bit hard to understand (and may compute cs/4 twice).