user2397282 user2397282 - 3 months ago 8
Swift Question

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?

Answer

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

Comments