简体   繁体   中英

Last digit of a large number(power) python

Found this on Codewars. The function takes two arguments A and B and returns the last digit of A^B. The code below passes the first two test cases, but won't pass the next ones.

def last_digit(n1, n2):
    number = n1**n2
    if number % 2 == 0:
        return number % 10
    elif number % 2 != 0:
        return number % 10

Test.it("Example tests")
Test.assert_equals(last_digit(4, 1), 4)
Test.assert_equals(last_digit(4, 2), 6)
Test.assert_equals(last_digit(9, 7), 9)
Test.assert_equals(last_digit(10, 10 ** 10), 0)

Don't compute n1**n2 . The problem comes when you attempt to compute:

10**(10**10)

That is a 1 followed by ten billion zeroes.

Use pow(n1, n2, 10) this makes the problem (more) tractable as it computes the exponentiation modulo 10 . Then as the number is already reduced modulo 10 the function can be rewritten as:

def last_digit(n1, n2):
    return pow(n1, n2, 10)

Problem is easy to solve once you realize that the last digits of powers form a cycle. For example:

2: 2, 4, 8, 6, 2, 4
3: 3, 9, 7, 1, 3, 9

With that in mind you can create the cycle first and then just index it with modulo of n2 :

def last_digit(n1, n2):
    if n2 == 0:
        return 1

    cycle = [n1 % 10]
    while True:
        nxt = (cycle[-1] * n1) % 10
        if nxt == cycle[0]:
            break
        cycle.append(nxt)
    return cycle[(n2 - 1) % len(cycle)]

This is also faster than using pow :

def last_digit_pow(n1, n2):
    return pow(n1, n2, 10)

if __name__ == '__main__':
    import timeit
    print(timeit.timeit("last_digit(10, 10 ** 10)", setup="from __main__ import last_digit"))
    print(timeit.timeit("last_digit_pow(10, 10 ** 10)", setup="from __main__ import last_digit_pow"))

Output (Windows 8 & Python 2.7):

0.832171277335
4.08073167307

Output (Windows 8 & Python 3.5):

0.6951034093766606
1.9045515428013722

Output with 10**100 (Windows 8 & Python 3.5):

0.8367381690724996
10.928452962508006

I know this post is old, but maybe someone will find this dictionary-based approach useful, too.

cycles = {
    0: [0,0,0,0],   
    1: [1,1,1,1],
    2: [2,4,8,6],
    3: [3,9,7,1],
    4: [4,6,4,6], 
    5: [5,5,5,5], 
    6: [6,6,6,6], 
    7: [7,9,3,1], 
    8: [8,4,2,6], 
    9: [9,1,9,1], 
}

def last_digit(n1, n2):
    if n2 == 0:
        return 1
    else:
        n1_last_digit = int(str(n1)[-1])
        cycle = cycles[n1_last_digit]
        return cycle[(n2 % 4) - 1]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM