Search code examples
python-2.7tracebackvalueerror

Why do i keep getting " ValueError: invalid literal for long() with base 10: '5-1'


I think the error means that it is receiving some other data type although it expects another kind but i may be wrong since i am a beginner at python.Anyone knows how this can be fixed?

#Program to calculate factorial of a long number

def multiply(multiplier,multiplicand):

    a = long(''.join(multiplier))
    b = long(''.join(multiplicand))
    a = a*b
    multiplier = list(str(a))
    b = b-1
    multiplicand = list(str(b))
    if(b == 1):
        return False,multiplier,multiplicand
    else:
        return True,multiplier,multiplicand


num = ""
f = True # A flag variable
while(f):                 #checks if the string consists of digits only
        num = raw_input("Enter number:")  
        f = False
        if num.isdigit() == False:
                print "oops,try again!"
                f = True
multiplier = list(num)
multiplicand = multiplier[:]
multiplicand.pop()
multiplicand.insert(len(multiplier),str(long(multiplier[-1])-1)) #mand now contains   multiplier -1 in list form 

f = True
while (f):
        f,multiplier,multiplicand = multiply(multiplier,multiplicand)
num = ''.join(multiplier)
print num  #print the ans as a string 

The code runs fine as long as the value entered is below 50,but after 50 it shows the error:

Traceback (most recent call last):
File "test.py", line 31, in <module>
    f,multiplier,multiplicand = multiply(multiplier,multiplicand)
File "test.py", line 5, in multiply
    b = long(''.join(multiplicand))
ValueError: invalid literal for long() with base 10: '5-1'

What does '5-1' mean?


Solution

  • You are treating multi-digit numbers as lists, and reimplementing substraction. You want mand = mplier - 1. Since mplier is a list of digits (there is no need for this, more information at the end of the answer) you are assuming that mand should be identical to mplier except the last digit, which should be the last digit of mplier minus 1.

    This holds true for numbers which do not end in 0: ['5', '3'] would become ['5', '2'], but ['5', '0'] would become ['5', '-1'], not ['4', '9']. When you try to reassemble your number in b = long(''.join(mand)) you end up with b = long('4-1'), and '4-1' is not a number, so you get an exception.

    Python does not have a precision limit on integer numbers, so you don't need to treat long numbers differently.

    I have rewritten your code in case it's useful:

    #Program to calculate factorial of a long number
    
    def factorial(n):
        result = 1
        for r in xrange(0, n):
            result = result * (r+1)
        return result
    
    num = 0
    
    while(True):                 #checks if the string consists of digits only
            num = raw_input("Enter number:")
            if not num.isdigit():
                    print "oops,try again!"
            else:
                num = int(num)
                break
    
    print factorial(num)
    

    Also, as a side note, the code is confusing and it took me a bit to understand what you were doing. You could probably benefit from CodeReview to learn best practices (useful variable names, getting rid of useless variables, proper documentation of the code, newest techniques...).