6

When generating a random CGFloat, I use the following code. Some explanation here

extension CGFloat{
     static func randomFloat(from:CGFloat, to:CGFloat) -> CGFloat {
          let randomValue: CGFloat = CGFloat(Float(arc4random()) / 0xFFFFFFFF)
          return randomValue * (to - from ) + from
      } 
}

It used to be OK. Works fine now.

There is a warning, after I upgraded to Swift 5.

'4294967295' is not exactly representable as 'Float'; it becomes '4294967296'

to the line of code

let randomValue: CGFloat = CGFloat(Float(arc4random()) / 0xFFFFFFFF)

How to fix it?

Sulthan
  • 128,090
  • 22
  • 218
  • 270
dengST30
  • 3,643
  • 24
  • 25

2 Answers2

12

As you know Float has only 24-bits of significand, so 32-bit value 0xFFFFFFFF would be truncated. So, Swift is warning to you that Float cannot represent the value 0xFFFFFFFF precisely.

The short fix would be something like this:

let randomValue: CGFloat = CGFloat(Float(arc4random()) / Float(0xFFFFFFFF))

With using Float.init explicitly, Swift would not generate such warnings.


But the preferred way would be using random(in:) method as suggested in matt's answer:

return CGFloat(Float.random(in: from...to))

or simply:

return CGFloat.random(in: from...to)
OOPer
  • 47,149
  • 6
  • 107
  • 142
7

Simplest solution: abandon your code and just call https://developer.apple.com/documentation/coregraphics/cgfloat/2994408-random.

matt
  • 515,959
  • 87
  • 875
  • 1,141
  • Not just simpler, but better. Don't overcomplicate things by reinventing the wheel. – Alexander Apr 07 '19 at 19:32
  • @Alexander Well, there's even more than that. The whole point of `random(in:)` is that `arc4random` is deprecated. – matt Apr 07 '19 at 20:10
  • Oh really? I thought it was the low-level API for accessing the random device that underpins the new random implementation – Alexander Apr 07 '19 at 20:14
  • 1
    Look at minute 27 of https://developer.apple.com/videos/play/wwdc2018/401 – matt Apr 07 '19 at 20:46