0

Lets take a look at this simple example

let formatter = NumberFormatter()
formatter.number(from: "0.945")?.decimalValue // result: 0.945
formatter.number(from: "0.94")?.decimalValue  // result: 0.9399999999999999

How can I achieve that "0.94" converts to Decimal with exact same value e.g. 0.94?

I prefer solutions with NumberFormatter because I want to use this String to Decimal conversion also for amounts with currency, such as "$0.94" and "0.94€"

Klemen
  • 2,144
  • 2
  • 23
  • 31
  • See [NSDecimalNumber round long numbers](https://stackoverflow.com/questions/3727142/nsdecimalnumber-round-long-numbers) – Willeke Jan 22 '21 at 10:41

1 Answers1

1

This website contains explanation. Basically, computers store these numbers using a system that can't represent them very accurately.
If you need to have better accuracy, I suggesting working with decimal types such as Decimal or NSDecimalNumber:

Decimal(string: "0.945")
Decimal(string: "0.94")
Jobert
  • 1,532
  • 1
  • 13
  • 37
  • Don't forget to mention that it only works if you use the string initializer. If you pass a float literal it may lose precision as well. – Leo Dabus Jan 20 '21 at 14:02
  • `Decimal(1234.999999999999)` would result in `1234.999999999998976` while using the string initializer `Decimal(string: "1234.999999999999")` would result in `1234.999999999999` – Leo Dabus Jan 20 '21 at 14:05
  • The point is not to use float literals since they can't be stored with accuracy. It makes no sense to initialize a Decimal using a float literal if you want to achieve that accuracy, that precision error will just be passed into the Decimal value. – Jobert Jan 20 '21 at 14:15
  • 1
    I know that but the OP probably doesn't. The same applies for future readers of this post. – Leo Dabus Jan 20 '21 at 14:21