Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift: Creating a double from a String appends 0000000000001 to the resulting number

I am trying to get a Double value from a UITextField using Double(myTextField.text!)!. The problem is, when I enter certain numbers I get 0000000000001 appended to the end of the number. For example, Double("9.05")! gives the value 9.050000000000001 instead of the expected 9.05.

Can anyone explain why this is happening, and how I get avoid / fix it?

Thanks in advance for any help.

like image 924
Benjy Wiener Avatar asked Oct 24 '25 09:10

Benjy Wiener


2 Answers

As several have noted, the underlying problem is that when you store 9.05 in binary, you get rounding errors. So it's not appending some value; it's showing you the correct value after rounding (in binary). This is very much like store 2/3 in decimal. You wind up with "6.66667" which seems wrong, but is due to rounding. 1/100 is "0.00000010100011110101..." in binary.

To get what you want, you need formatting. Ashish gives a working example, but it's become easier in more recent builds of Swift. You don't need as NSString anymore:

import Foundation
let strVal = "9.05"
let doubleVal = Double(strVal)! // Convert String to Double
let formattedStr = String(format: "%.2f", doubleVal) // Double -> String w/ formatting
print(formattedStr)

You may be confused about the difference between the double value and how it is represented as decimal digits. You can't express 9.05 in a finite number of binary digits, just like you can't express 2/3 in a finite number of decimal digits. There will always be some rounding error. That's why, for instance, you cannot safely compare with == two floating point numbers.

If what you really want is to do decimal math, then you have two choices:

  • Work in fixed point rather than floating point. Multiply everything by 100 and store it as an Int. For many problems is this an ideal solution.
  • NSDecimalNumber. This is available in Cocoa and lets you do math in decimal rather than binary. 9.05 as an NSDecimalNumber is exactly 9.05. This is a good solution for more general problems, but is a little harder to implement.
like image 67
Rob Napier Avatar answered Oct 26 '25 00:10

Rob Napier


That is a general problem of binary representations of a floating point digits where 9.05 cannot be represented exactly.

Try this in a playground:

9.05 // 9.050000000000001

so even directly initializing the value is not a "workaround"

like image 28
Qbyte Avatar answered Oct 26 '25 00:10

Qbyte



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!