Python中除法的奇怪行为

9
“我正在尝试在Hackerrank上解决这个问题:euler003。在某些时候,我必须检查一个数字是否能够被n(给定的输入)整除。

这个代码完美地工作,除了一个测试用例(没有问题):


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)

现在你可以看到,当i是n的因数时,我只会对这个数字进行除法。例如,如果数字为i=2和n=4,则n/2和n//2没有任何区别。
但是,当我使用下面的代码时,所有测试用例都失败了:
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)

这不是第一次了,即使对于这个问题,我也遇到了同样的情况。对于这个问题,我只需要除以2,所以我使用了右移运算符来摆脱这个问题。但在这里我什么都做不了,因为右移无法帮助我。
为什么会这样?如果数字很小,我看不出有任何区别,但随着数字变大,它会以某种方式表现出不同的行为。
甚至当/失败时,使用//也不直觉。这是什么原因?

3
在Python 3中,n / 2和n // 2是不同的。4/2 == 2.0和4//2 == 2。 - Mitiku
是的,你说得对。但在我的情况下,如果数字是3和2,它将不会进入循环。只有当3%2为0时,它才会进入循环。因此,3和2没有进入循环的机会。 - Bharat
1
@JamesKPolk: 对于这个特定的问题,(2)不是一个问题,因为所有的整数都将在可表示的范围内(根据问题描述,最大的 n10**12),而且所有的浮点除法和取模运算应该得到精确的结果。但我完全同意第(3)点。 - Mark Dickinson
3
我不理解你的第一份代码是如何工作的。我认为当“n”是奇平方数时会失败。(“range”除去第二个端点) - trent
1
@JamesKPolk:我怀疑失败只是由于整数浮点数被打印时带有尾随的.0。因此,对于输入51(例如),该网站期望输出字符串"17",但实际得到的是"17.0" - Mark Dickinson
显示剩余12条评论
1个回答

9
n // in / i之间的区别主要是基于以下原因,假设niint类型且n % i == 0

  1. n // i的类型仍为int,而n / i的类型为float
  2. 在Python中,整数具有无限精度,而浮点数的精度是有限的。

因此,如果n // i的值超出了Python float类型可以准确表示的范围,则它将不等于计算得到的值n / i

举个例子:

>>> (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
>>> 

1
“arbitrary” 的翻译应该是“任意的”,而不是“无限的”。 - pvg
谢谢,你已经清楚地说明了正在发生的事情!! - Bharat

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接