0

I'm trying to subtract to floating point numbers in python. I've values

a = 1460356156116843.000000, b = 2301.93138123

When I try to print a-b, it's resulting the value 1460356156114541.000000 contrary to the actual value 1460356156114541.06861877.

What are the limitations in python while doing floating point arithmetic. Is there any way in python through which I can get the actual result of this subtraction?

Divya
  • 393
  • 2
  • 5
  • 17
  • 2
    It looks like python is making integer subtraction or parsing the result to integer. Can you show exactly how you assign the values and how you calcualte the result? Just copy-paste the related code block please. – Mp0int Apr 11 '16 at 06:58
  • 1
    See also http://sopython.com/canon/87/why-is-this-particular-floating-point-math-operation-not-giving-the-correct-answ/ – tripleee Apr 11 '16 at 07:02
  • 1
    Floating-point numbers basically represent significant digits, so you can't keep track of small differences between large numbers. Since your `a` is 16 digits long there isn't "room" left to also represent the fractional difference. What context are you in that you need to keep track of differences that are so small relative to the numbers involved? – BrenBarn Apr 11 '16 at 07:03

3 Answers3

3

Python has the same limitations for floating point arithmetic as all the other languages. You can use Decimal to get the accurate result:

from decimal import Decimal

a = Decimal('1460356156116843.000000')
b = Decimal('2301.93138123')

print a - b # 1460356156114541.06861877
niemmi
  • 17,113
  • 7
  • 35
  • 42
1

Python uses IEEE 754 doubles for its floats. So you should treat anything after 15 significant figures or so as science fiction. And that's just for a freshly-initialised number. When you start doing operations with floats you can lose more precision, especially doing addition or subtraction between numbers that differ significantly in absolute magnitude.

OTOH, doing subtraction between numbers very close to each other in magnitude can lead to catastrophic cancellation.

If you are careful, you can reduce the impact of these problems, but you do need a good understanding of how floating-point arithmetic works, and well-behaved data.

Alternatively, you can work with a library that provides higher precision, eg Python's Decimal module. You still need to take care to avoid catastrophic cancellation and the other problems that lead to loss of significance, but at least you've got more significant digits to play with.

The Decimal module just provides basic arithmetic operations. If you need advanced mathematical functions like trig and exponential functions, take a look at the excellent 3rd-party arbitrary precision mathematics module mpmath. It can handle complex numbers, solve equations, and provides some calculus operations.

PM 2Ring
  • 54,345
  • 6
  • 82
  • 182
0

Using decimal is convenient. But for the sake of demonstration regarding the importance of keeping significant digits, let me throw in this example.

import sys
print(sys.maxsize)
9223372036854775807 # for 64 bit machine, the max integer number. But it can grow as needed.

So for the above case you can do the computation in two steps.

1460356156116842 - 2301 = 1460356156114541  # all integer digits preserved
1 - .93138123 = 0.06861877 # all significant float digits preserved.

So the answer would be adding the two. But if you do that you will lose all float digits. The 64bit is not big enough to keep all digits.

Hun
  • 3,707
  • 2
  • 15
  • 15