-6

Suppose I have a Double and I create an Int from the Double:

var a : Double = 4.0
var b = Int(a)

In the past, the above code could result in b=3 if a was internally represented as 3.999999999999999. Do we not have to worry about this anymore in Swift? What is the correct way to cast a Double to an Int?

statguy
  • 1,627
  • 3
  • 13
  • 22

3 Answers3

1

You're using generic initializer init(_:) which creates an integer from the given floating-point value, rounding toward zero.

So, there is well known problem with saving types based on floating point math (see this). Because of that, your a can be saved for example as 3.99999999999999994. Then, if you use this Int initalizer from this Double, it creates Int rounded toward zero... (3)


One way is rounding your Double value before it will be passed for Int initializer to one decimal place

round(a*10)/10

and then round result by following rule

>= 0.5  round up
< 0.5   round down

For this purpose you can use rounded method with FloatingPointRoundingRule .toNearestOrAwayFromZero (which is default value for this parameter)

var a: Double = 3.499999999
var b = Int((round(a*10)/10).rounded()) // b = 4

Also you can use failable initalizer, since if Double is bigger then Int can be, code crashes

var a: Double = .greatestFiniteMagnitude
if var b = Int(exactly: (round(a*10)/10).rounded()) { ... } // nil
Robert Dresler
  • 10,580
  • 2
  • 22
  • 40
  • My main question is, if I have an arbritary double, it could be represented as 3.99999999, 4.00000000, or 4.000000001, as examples. So I am looking for the proper way to do Double -> Int. I wasn't looking for a way to set a variable to 4! – statguy Mar 20 '19 at 07:25
  • 1
    @statguy There is no such thing as `proper way to do Double -> Int`. Pick a rounding method. – Desdenova Mar 20 '19 at 07:45
  • `.toNearestOrAwayFromZero` is the default rounding rule, you can simply write `Int(a.rounded())` – Martin R Mar 20 '19 at 07:51
  • @MartinR right, thank you. :-) – Robert Dresler Mar 20 '19 at 07:54
0
let roundedVal = round(a)
var b = Int(roundedVal)
0

You should use prototype Double.rounded() before casting it to Int. So a double number like 3.99999999999... or 4.000000000001 becomes 4:

var a : Double = 3.999999999999
var b = Int(a.rounded(.toNearestOrAwayFromZero))
print(Int(a)) // output: 3
print(b) // output: 4
ngbaanh
  • 440
  • 2
  • 12