0

I have been using python for a while now and I am quite comfortable using it, but I have encountered a really weird problem, for some reason when I try to input a large number and use int() to convert it to integer the number is always off. This is a code for a codeforces problem, the logic is correct but for some reason if I input n=99999999999999999, what happens is that n will equal 10^18. I am assuming it's an approximation by python, how can I avoid that ?

t=int(input())
for _ in range(t):
    n=int(input())
    if n<10:
        print(n)
    else:
        flag=True
        while flag:
            for i in range(int(math.log10(n))+1):
                digit=n%(10**(i+1))//(10**i)
                if digit==0:
                    continue
                if not (n%digit==0):
                    break
                if i==int(math.log10(n)):
                    print(n)
                    flag=False
            n+=1   
Mohamed Rady
  • 118
  • 1
  • 6
  • See [this post](https://stackoverflow.com/questions/7604966/maximum-and-minimum-values-for-ints) on max and min values in Python. – A Bear Dec 20 '20 at 19:16

2 Answers2

0

In fact, n is correct, but math.log10() works on floats, not integers, so there's a rounding error, although I'm not sure where exactly. See also: Is floating point math broken?

BTW, you're off by an order of magnitude: 10^17, not 10^18.

>>> n = 99999999999999999
>>> n
99999999999999999
>>> math.log10(n)
17.0
>>> float(n)
1e+17

To ultimately fix the problem, see Is floating point arbitrary precision available? For example:

>>> from decimal import Decimal
>>> d = Decimal(10**17-1)
>>> d
Decimal('99999999999999999')
>>> d.log10()
Decimal('16.99999999999999999565705518')
>>> int(d.log10())
16
wjandrea
  • 28,235
  • 9
  • 60
  • 81
0

You could replace int(math.log10(n)) by len(n)-1. Staying completely within int, Python should support "arbitrarily large" numbers.

import math

t = int(input())
for _ in range(t):
    n=int(input())
    if n<10:
        print(n)
    else:
        flag=True
        while flag:
            for i in range(len(str(n))):  # < here
                digit=n%(10**(i+1))//(10**i)
                if digit==0:
                    continue
                if not (n%digit==0):
                    break
                if i==len(str(n))-1:  # < and here
                    print(n)
                    flag=False
            n+=1

I didn't check your algorithm apart from that :)

matheburg
  • 2,097
  • 1
  • 19
  • 46