I am running the following code and getting contradictory results:

My Code:

import math
n=420
k=8
x = (math.factorial(n - 1)) / (math.factorial(n - k))
y = (math.factorial(k))
print(x)
print(y)
print(x/y)
print(x%y)
print(x//y)

Output:

2.1558482112674708e+18

40320

53468457620721.0

128.0

53468457620721.0

Please note that the third result shows x is divisible by y but the fourth result shows there is a remainder which means x is not divisible by y. I am quite baffled, could you please look into it and advise me a solution.

>>> 53468457620721.0 + 128.0/40320
53468457620721.0

The problem here is that floating point numbers have limited precision. The number on the left of this addition is large, so it is stored in a way such that the small number on the right falls smaller than its precision. With floats, the bigger the number, the bigger the approximation.

So, your problem is that the “.0” is a numeric approximation. There would be further digits if the computation were exact, but it is not.

Moreover, your variable x is stored as a floating point number, which entails a loss in precision, as you can see from the e+18.

Use integer operators (// and %) for exact results on integers.

n = 420
k = 8
x = math.factorial(n-1)//math.factorial(n-k)
y = math.factorial(k)
print(x)
print(y)
print(x//y)
print(x%y)

The problem is that the factorials you are working with are way too
big to represent as floats exactly.

You have these two values:

>>> a = math.factorial(420-1)  # 419*418*417*...*3*2*1
>>> b = math.factorial(420-8)  # 412*411*410*...*3*2*1

These are huge numbers. a has over 900 digits:

>>> len(str(a))
919

The largest whole number floats can store exactly is 2**53, after
which you start to get rounding errors:

>>> x = 2**53
>>> float(x) == x
True
>>> float(x) + 1 == x + 1
False

That number has only 18 decimal digits, about 900 short of the
requirement to store the factorials above. So as soon as you convert to
floats using the / operator, you lose accuracy:

>>> a/b  # Division done using floating point maths
2.1558482112674708e+18
>>> a//b  # True value, done exactly with integer maths
2155848211267470720

So the true result, which should end with 70720, gets rounded off to
ending with 70800 instead.

See the tutorial and the FAQs:

https://docs.python.org/3/tutorial/floatingpoint.html

https://docs.python.org/3/faq/design.html#why-are-floating-point-calculations-so-inaccurate

Thank you very much.

Thank you very much for your help.