0
a = 1000000000
b = 1000000    
max_ = int((a - b + 1) * (a - b) / 2)

I have this line in my code and when "a" equals a billion (1000000000) and "b" equals a million (1000000), the result came up with the answer "499000500499500032". The correct result of this arithmetical calculation is "499000500499500000".

I searched for why it does so but couldn't find anything. I am using Python 3.9.5 if it matters in this case .

Onur Eker
  • 11
  • 4
  • Please update thet script with the initial values for the variables so we can run it with a quick copy/paste. – tdelaney Jul 06 '21 at 17:04
  • are `a` and `b` both `int`egers, or `float`ing point numbers? If they're floating point, it may be due to limited precision – TimD1 Jul 06 '21 at 17:04
  • 3
    You're using float division, which has limited precision. Use `//` instead of `/` – khelwood Jul 06 '21 at 17:05
  • 2
    [What Every Computer Scientist Should Know About Floating-Point Arithmetic](//docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html) – Pranav Hosangadi Jul 06 '21 at 17:05
  • a and b are assigned with input() @tdelaney. – Onur Eker Jul 06 '21 at 17:12
  • a and b are both integers which are casted by int(). @TimD1 – Onur Eker Jul 06 '21 at 17:13
  • Nevertheless you can hard-code the initialisation in the code in your question (and test it, of course), can't you? A [mre] makes it much easier for anyone to see the problem you're seeing, and therefore you're more likely to get help. – DisappointedByUnaccountableMod Jul 06 '21 at 17:14
  • This works well but I do not understand why it is 32 at the end when I use /. I do know / is float division. What if result is not integer? How can I correctly calculete if the result is not integer? @khelwood – Onur Eker Jul 06 '21 at 17:18
  • Read the link provided by @PranavHosangadi – TimD1 Jul 06 '21 at 17:20
  • I fulfilled your advise and edited the question. @barny – Onur Eker Jul 06 '21 at 17:21
  • I actually know how floating numbers work. But the thing that I don't understand is why result is 32 more than actual answer since divisor, result and dividing numbers are integers. @TimD1 ,@PranavHosangadi – Onur Eker Jul 06 '21 at 17:25
  • 2
    @OnurEker - Its because 499000500499500000 itself can't be represented by `float` on a 64 bit machine. When you did `/ 2` you made the right hand side into a float. You then make it back into an int, but the precision was already gone. The question is whether this matters for your particular calculation. If it does, you may need to move to a higher precision package. – tdelaney Jul 06 '21 at 17:30
  • A different option is to do floor division `(a - b + 1) * (a - b) // 2` ... I'll note that in my answer. – tdelaney Jul 06 '21 at 17:31

1 Answers1

2

Python uses the CPU's native float which is a binary estimate of the true floating point number. Its not a problem with python per se, its the inherent imprecision in fixed length binary floats. Simply writing your wanted value as a float demonstrates the problem:

>>> f"{499000500499500000.:f}"
'499000500499500032.000000

If you need more precision than float offers, the decimal module may work for you.

>>> from decimal import Decimal
>>> a = Decimal(1000000000)
>>> b = Decimal(1000000)
>>> max_d = (a - b + 1) * (a - b) / 2
>>> max_d
Decimal('499000500499500000')
>>> max_ = int(max_d)
>>> max_
499000500499500000

float exists, even though it is an estimate of a true real number, because this lack of precision can usually be factored into the algorithm. When this error is too much, or when you are doing something like accounting where the error is significant, there is the alternative decimal.

See Floating Point Arithmetic: Issues and Limitations

Another option is to use floor division which doesn't go through float.

>>> a = 1000000000
>>> b = 1000000
>>> (a - b + 1) * (a - b) // 2
499000500499500000

That looks better! But, there is still a lack of precision depending on what you are dividing.

tdelaney
  • 73,364
  • 6
  • 83
  • 116