【问题标题】:Integer overflow encountered in sumsum中遇到整数溢出
【发布时间】:2019-09-24 04:43:54
【问题描述】:

我的印象是 python 整数是任意精度。但是今天在解决a leetCode problem 和多次提交错误答案时,我终于将mod 添加到我的解决方案中并且它起作用了。我对它发生的原因感到困惑,以下是我的代码:

import math

class Solution:
    def numRollsToTarget(self, d: int, f: int, target: int) -> int:
        if target>d*f or target<d:
            return 0
        memo = {}
        return int(self.recurse(d,f,target,memo)%(math.pow(10,9) + 7))

    # def recurse(self,d,f,target,memo):

    def recurse(self,d,f,target,memo):
        key = "%d %d"%(d,target)
        if key in memo:
            return memo[key]
        if d*f<target or target<d:
            return 0
        elif d==1:
            return 1
        else:
            ways = 0
            for i in range(1,f+1):
                # following line uncommented, and the next one commented, gives correct answer
                #ways = (ways+self.recurse(d-1,f,target-i,memo))%(math.pow(10,9) + 7)
                ways += self.recurse(d-1,f,target-i,memo)

            memo[key] = ways
            return memo[key]

我的猜测是溢出导致了错误的结果,每次求和时都修改部分结果可以解决问题。还是我还缺少其他东西?

【问题讨论】:

  • 您介意再详细说明一下这个问题吗?
  • 是什么让你觉得这里有整数溢出?
  • @Goyo,这是我的猜测,还有什么可能导致这种情况?只需添加 mod 即可解决问题。
  • 不,你说得对,python 整数是任意精度的。但是您正在使用浮点数进行计算,这些浮点数不是也不能准确地表示大整数。这可能是导致错误结果的原因,并且通过 coincidence 对其进行修改。或者,也许您只是弄错了,而改装实际上是解决问题的正确方法。无论哪种方式,如果您想使用整数,请使用 ** 运算符而不是 math.pow()
  • 但是我没有使用float进行计算。我在这里发布的代码版本,最后只做 math.pow() ,这是给出错误答案的版本。带有 math.pow() 的版本(注释行)实际上给出了正确的答案(但不是因为 float,而是因为 mod)。

标签: python python-3.x integer-overflow


【解决方案1】:

您正在使用浮点数进行计算:

return int(self.recurse(d,f,target,memo)%(math.pow(10,9) + 7))

这会强制使用浮点数计算模数,这不是整数溢出,而是浮点数不准确导致您得到错误结果。

让我们创建d, f, target = 30, 30, 500。然后int(self.recurse(d, f, target, memo) 返回1319186227454333254490768998141738589030871,一个int,而math.pow(10, 9) + 71000000007.0,一个float

这就是你正在做的事情:

print(1319186227454333254490768998141738589030871 % 1000000007.0)  # wrong
811448245.0

如果您改为确保被除数也是整数(10 ** 9 + 71000000007):

print(1319186227454333254490768998141738589030871 % 1000000007)  # right   
222616187

【讨论】:

  • 有趣,是的,这就是问题所在。我从10**9+7 开始,但在修复代码中的另一个错误时将其替换为math.pow(),这是一个严重的错误。
  • 确实如此。当涉及浮点数时,我个人认为模数和地板除法是未定义的行为。
猜你喜欢
  • 2017-11-15
  • 2020-08-30
  • 1970-01-01
  • 1970-01-01
  • 2018-07-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多