Reputation: 47
I wrote a simple program to count the number of digits in n+1 where n is a large integer.The following test case outputs the answer as 34 but the answer is 33. Test case - 999999999999999999999999999999990
Code -
#python3
import math
inp = eval(input())
if inp > 0:
digits = int(math.log10(inp+1))+1
elif inp == 0:
digits = 1
else:
digits = int(math.log10(-inp))+2
print(digits)
When I input a smaller integer,say 10 digits, it shows the correct answer, for example when input = 9999999990, output is 10, which is correct.
Upvotes: 0
Views: 123
Reputation: 317
math.log10() will evaluate to a double precision floating point number. It doesn't have enough precision to tell the result and the number 33 apart. You can use mpmath to evaluate log10 with higher precision. This code worked for me:
#python3
from mpmath import mp
mp.prec = 127 # set the precision to 127 bits
inp = int('999999999999999999999999999999990')
if inp > 0:
digits = int(mp.log10(inp))+1
elif inp == 0:
digits = 1
else:
digits = int(mp.log10(-inp))+2
print(digits)
Note that the precision is set to 127 bits. When evaluating a 40-digits number, we will run into the same problem as we had before. When the 40-digit number is very close to 10^41, the result of log10 might be a little bit more than 41 while the real value is a little bit less. This is why converting it so an integer yields 41. Let's estimate how much precision is sufficient: The derivation of log10(x) is 1 / (x * ln(10)). So log10(x+1) - log10(x) is about 1 / (x * ln(10) ) for high x. We need a relative precision of about Delta_y / y, where Delta_y is ( log10(x+1) - log10(x) ) and y is log10(x). We can estimate the number of binary digits with log2( 1 / relative_precision ). This yields us log2( x * ln(x) ). For an x of 39 nines and one zero, this gives us about 139.4. So if we put
mp.prec = 140
we will get the correct result. Indeed
#python3
from mpmath import mp
mp.prec = 140
inp = int(39 * '9' + '0')
if inp > 0:
digits = int(mp.log10(inp))+1
elif inp == 0:
digits = 1
else:
digits = int(mp.log10(-inp))+2
print(digits)
print( len( str(inp) ) )
outputs:
40
40
Note that this might not be the best way of evaluating the number of digits. You could for example just use a loop, dividing by 10 each step. Or simply put
print( len( str(inp) ) )
Upvotes: 1