2

How to correctly add or subtract using floats? For example how to perform:

2.4e-07 - 1e-8

so that it returns 2.3e-7 instead of 2.2999999999999997e-07.

Converting to int first yields unexpected results, the below returns 2.2e-07:

int(2.4e-07 * 1e8 - 1) * 1e-8

Similarly,

(2.4e-07 * 1e8 - 1) * 1e-8

returns 2.2999999999999997e-07.

How to perform subtraction and addition of numbers with 8 decimal point precision?

2.2999999999999997e-07 is not sufficient as the number is used as a lookup in a dictionary, and the key is 2.3e-7. This means that any value other than 2.3e-7 results in an incorrect lookup.

Greg
  • 8,175
  • 16
  • 72
  • 125
  • If you need exact decimal values you should think whether floating point variables are the right tool for the job since they are always an approximation. See https://stackoverflow.com/questions/588004/is-floating-point-math-broken – piet.t Apr 04 '19 at 13:34
  • You are already performing the addition with much better than 8 decimal point precision. – Patricia Shanahan Apr 04 '19 at 16:51

3 Answers3

2

I suggest using the decimal data type (it is present in the stardard installation of Python), because it uses fixed precision to avoid just the differences you are talking about.

>>> from decimal import Decimal
>>> x = Decimal('2.4e-7')
>>> x
Decimal('2.4E-7')
>>> y = Decimal('1e-8')
>>> y
Decimal('1E-8')
>>> x - y
Decimal('2.3E-7')
Ralf
  • 16,086
  • 4
  • 44
  • 68
  • How to deal with this when the original data is a float instead of a string? Is this a good approach `Decimal('%.8f' % 2.4e-7) - Decimal('%.8f' % 1e-8)` or is there a more correct/better way of doing it? – Greg Apr 04 '19 at 13:46
  • @Greg yes, that string formatting is probably your best bet to get Decimal objects – Ralf Apr 04 '19 at 13:48
1

It's really just a way of skirting around the issue of floating point arithmetic, but I suggest using the decimal package from the standard library. It lets you do exact floating point math.

Using your example,

$ from decimal import Decimal
$ x = Decimal('2.4e-7')
$ y = Decimal('1e-8')
$ x-y
Decimal('2.3E-7')

It's worth noting that Decimal objects are different than the float built-in, but they are mostly interchangeable.

Andrew F
  • 2,690
  • 1
  • 14
  • 25
1

I do not know if it is what you are looking for but you can try that kind of thing:

a = 0.555555555
a = float("{0:.2f}".format(a))
>>> 0.56

I hope it will help you!

Adrien

AdForte
  • 305
  • 2
  • 12