Search code examples
pythonmultiplicationfactorialdigit

Factorial nonzero digits don't match


Here is a simple program to find the last several non-zero digits of the product of the numbers 1 through 105, removing trailing zeros along the way:

def f(a, b):
    s = 1
    for i in range(a, b+1):
        s *= i
        while not s % 10:
            s //= 10
        s = s % 10**10
    return s

f(1, 10**5) and f(10**5+1, 2*10**5) do not produce the same last 5 digits, though mathematically they should.

Additionally, f(1, 10**5)**10 does not produce the same ending digits as f(1, 10**6).

Where is the problem here and what is the correct implementation?


Solution

  • Your code correctly finds the last ten digits after the rightmost zero digits are discarded. Your belief that the code is incorrect rests on a pair of fallacious claims.

    First you claim that the product of 1 through n, or n!, should have the same non-zero digits as the product of n+1 through 2n, which is:

    (n+1)*(n+2)*...*(2n)  =  (2n)! / n!
    

    In saying that the non-zero digits of n! and (2n)!/n! should be equal, you are implying that for some constant k, we have:

    10^k * n!  =  (2n)! / n!
    

    But this is false in general. Consider this counterexample:

    20! = 2432902008176640000
    40! / 20! = 335367096786357081410764800000
    

    Your second claim is that n! raised to the power of 10 is the same as (10n)!. This is false. In general, it is not true that:

    (n!)^k  =  (kn)!
    

    Counterexample:

    3!^10 = 60466176
    30! = 265252859812191058636308480000000
    

    I generated these figures with the following function:

    def series(start, end):
        x = start
        for i in range(start + 1, end + 1):
            x *= i
        return x
    

    For example, to see that the product of 1 through 100 does not have the same non-zero digits as the product of 101 through 200, execute:

    print(series(1, 100))
    print(series(101, 200))
    

    The first yields a number whose last five digits after removing the rightmost zeros are 16864. For the second, they are 02048.