Why is it like this?

Please have a look at the below statements…
print(((0.08 * 500 * 5) * 45) / 100)
print(((0.08 * 500 * 5) / 100) * 45)

print(((0.08 * 500 * 6) * 45) / 100)
print(((0.08 * 500 * 6) / 100) * 45)

print(((0.08 * 500 * 7) * 45) / 100)
print(((0.08 * 500 * 7) / 100) * 45)

print(((0.08 * 500 * 8) * 45) / 100)
print(((0.08 * 500 * 8) / 100) * 45)

print(((0.08 * 500 * 9) * 45) / 100)
print(((0.08 * 500 * 9) / 100) * 45)

print(((0.08 * 500 * 17) * 45) / 100)
print(((0.08 * 500 * 17) / 100) * 45)

print(((0.08 * 500 * 19) * 45) / 100)
print(((0.08 * 500 * 19) / 100) * 45)

OITPUTS:
90.0
90.0
108.0
108.0
126.0
125.99999999999999
144.0
144.0
162.0
162.0
306.0
306.0
342.0
342.0

Why do I get this value (125.99999999999999) for the above BOLD marked line of code?

Please have a look at the below statements…
print(((0.08 * 500 * 5) * 45) / 100)
[…]

The short answer is that Python floating point values (eg your 0.08 and
everything which is computed from it) effectively base 2 scientific
notation: a primary value integral (the mantissa) multiplied by an
integral scale factor (the exponent).

As such, various values cannot be precisely represented in it.

You may know that in base 10, for example, the fraction 1/3 cannot be
written precisely in the form 0.333333 because an infinite number of 3s
would be required. This is essentially because 10 has the prime factors
2 and 5, and there’s no 3 there.

The situation is analogous in base 2. 0.08 is 4/25 or 4/(5*5), and
there’s no 5 in the prime factors of 2.

We get around these issues for the most poart by having quite a few
digits of precision. Example:

 >>> 1.0/3.0
 0.3333333333333333

That isn’t 1/3, but it is quite close.

Your example computations have exposed that the value you supplied as
0.08 is not, in fact, _stored exactly equivalent to 4/25, just very
close.

When you do your arithmetic, the results aren’t exactly what you
anticipate, but because of the high precision the resulting value,
written in base 10 in the most accurate form, is usually so close that
it ends in .0000000000 and thus .0 when you trim the trailing zeroes.
But one of your computations resulted in a value where the most accurate
form is off enough to not end in all zeroes.

You can read about floating point here:

and there’s any number of tutorials discussing the details.

The short answer is that a floating point value is a fixed size
fraction; being fixed size means that many values cannot be precisely
represented.

Python has some modules for special purposes, such as decimal:

and fractions:

They’re slower than floating point and have their own limitations.

Cheers,
Cameron Simpson cs@cskk.id.au

The answer to your question is the same as the previous time you asked it.

Hello Cameron,
That is OK what you had explained.
But note that the 2 code lines below

print(((0.08 * 500 * 7) * 45) / 100)
print(((0.08 * 500 * 7) / 100) * 45)

give 2 different outputs as below, WHY ?
126.0
125.99999999999999

But in scientific Calculator,
they produce the same result as 126.0
Mathematically they should be same, is it not ?

Yes, they are mathematically the same.

No, they are not the same in binary FP calculations – please do go read the referenced materials.

NOTE: Floating point is HARD. I have a PhD in Engineering, do this stuff everyday, and I still get confused.

The short version is that FP calculations are not exact, and thus you will get results that are not exact, but should be very close to the exact answer. never rely on equality of a the result of a floating point calculation:

In [8]: a = ((0.08 * 500 * 7) * 45) / 100

In [9]: b = ((0.08 * 500 * 7) / 100) * 45

In [10]: a == b
Out[10]: False

In [11]: math.isclose(a,b)
Out[11]: True

Your calculator gives different results for one of a couple reasons:

  1. It’s rounding differently / or ordering operations differently
  2. It’s using a decimal representation internally – some are made that way, for less “surprising” results.

Hello Christopher.
Thank you so much for your excellent explanation.