9

I'm trying to solve this problem in hackerrank. At some point I have to check if a number divides n(given input) or not.

This code works perfectly well except one test case(not an issue):

if __name__ == '__main__':
    tc = int(input().strip())
    for i_tc in range(tc):
        n = int(input().strip())
        while n % 2 == 0 and n is not 0:
            n >>= 1
        last = 0



        for i in range(3, int(n ** 0.5), 2):
            while n % i == 0 and n > 0:
                last = n
                n = n // i        # Concentrate here


        print(n if n > 2 else last)

Now you can see that I'm dividing the number only when i is a factor of n.For example if the numbers be i = 2 and n = 4 then n / 2 and n // 2 doesn't make any difference right.

But when I use the below code all test cases are getting failed:

if __name__ == '__main__':
    tc = int(input().strip())
    for i_tc in range(tc):
        n = int(input().strip())
        while n % 2 == 0 and n is not 0:
            n >>= 1
        last = 0
        for i in range(3, int(n ** 0.5), 2):
            while n % i == 0 and n > 0:
                last = n
                n = n / i      # Notice this is not //
        print(n if n > 2 else last)

This is not the first time.Even for this problem I faced the same thing.For this problem I have to only divide by 2 so I used right shift operator to get rid of this.But here I can't do any thing since right shift can't help me.

Why is this happening ? If the numbers are small I can't see any difference but as the number becomes larger it is somehow behaving differently.

It is not even intuitive to use // when / fails. What is the reason for this ?

Bharat
  • 1,044
  • 15
  • 34
  • What is your Python version? – igrinis Oct 03 '17 at 13:13
  • It is python 3. – Bharat Oct 03 '17 at 13:13
  • 3
    in python 3 n / 2 and n // 2 are different. 4/2 ==2.0 and 4//2 == 2 – Mitiku Oct 03 '17 at 13:14
  • Even it is a float number it should be same right ? Since the number is a factor and 1.0 and 1 should not make any difference – Bharat Oct 03 '17 at 13:15
  • It could still produce different results. `/` is floating point division, while `//` is floor division (also called, integer division). `3 / 2 == 1.5`, but `3 // 2 == 1`. Watch out for this behaviour. – Sean Francis N. Ballais Oct 03 '17 at 14:02
  • Yes you are correct. But in my case if the numbers are 3 and 2 it will not enter into the loop. It enters into loop iff 3 % 2 is 0. So there is no chance that 3 and 2 enter into the loop – Bharat Oct 03 '17 at 14:12
  • A1) Actually according to the question in hackerrank n is a number to which we have to find the greatest prime factor. So n won't be float obviously.A2) what "n is not 0" does is check whether if n became 0 or not. For example if the given number is 16 so the while loop continuously divides the number and at some point it becomes 0 so it still keep on dividing that number. So to prevent that I added that condition – Bharat Oct 03 '17 at 14:15
  • Try running the `/`-version of your code with `n=51`. The output will be `17.0`, not `17`. BTW, never use `is` to compare numbers: `n is not 0` should be `n != 0`, but that's probably not why your code is failing. – Mark Dickinson Oct 03 '17 at 14:25
  • 1) If `n` is an int, then `n=n/2` will make `n` a float even if 2 divides n. 2) floats can only represent a limited range of integers exactly. 3) Why not use `//`? – President James K. Polk Oct 03 '17 at 14:39
  • 1
    @JamesKPolk: For this particular problem, (2) isn't an issue, since all integers will be in the representable range (from the problem description, the max `n` is `10**12`), and all the floating-point divisions and modulo operations should be giving exact results. But I wholeheartedly agree with point (3). – Mark Dickinson Oct 03 '17 at 14:43
  • 3
    I don't understand how your first code works. I believe it fails when `n` is an odd square number. (`range` excludes the second endpoint) – trent Oct 03 '17 at 15:18
  • @JamesKPolk Yeah we can use //. But just think how these small small things decide rank in the leader board.I don't have any problem using // but I just want to know why I'm doing this. – Bharat Oct 03 '17 at 15:39
  • @MarkDickinson: thanks, you're right. I guess I'm still unsure of what is an example input for which this "fails", and what is considered failure. – President James K. Polk Oct 03 '17 at 15:40
  • 1
    @JamesKPolk: I suspect the failure is simply to do with integral floats being printed out with a trailing `.0`. So for an input of `51` (for example), the site expects the string `"17"` as output, but gets `"17.0"` instead. – Mark Dickinson Oct 03 '17 at 15:41
  • @MarkDickinson thanks for telling me not to use "is". I actually migrated from java and I have noticed the side effects of using "is" like when I compare two objects it gives False and I know the reason that they are not pointing to the same memory location. But it's fun using for numbers !! – Bharat Oct 03 '17 at 15:41
  • @MarkDickinson: ah, I see, the scoring robot is failing the submission, got it now. – President James K. Polk Oct 03 '17 at 15:42
  • @trentcl your point helped me to get 100% correct answer.Thanks – Bharat Oct 03 '17 at 15:46

1 Answers1

9

The main reason of the difference between n // i and n / i given that n and i are of type int and n % i == 0 is that

  1. the type of n // i is still int whereas the type of n / i is float and
  2. integers in Python have unlimited precision whereas the precision of floats is limited.

Therefore, if the value of n // i is outside the range that is accurately representable by the python float type, then it will be not equal to the computed value of n / i.

Illustration:

>>> (10**16-2)/2 == (10**16-2)//2
True
>>> (10**17-2)/2 == (10**17-2)//2
False
>>> int((10**17-2)//2)
49999999999999999
>>> int((10**17-2)/2)
50000000000000000
>>> 
Leon
  • 31,443
  • 4
  • 72
  • 97