零除错误:浮点数除法

2 投票
3 回答
10953 浏览
提问于 2025-04-16 23:29

我有一段代码是用来解决牛顿法的。但是它出现了“除以零”的错误。我搞不清楚哪里出了问题。谢谢。

import copy

tlist = [0.0, 0.12, 0.16, 0.2, 0.31, 0.34] # list of start time for the phonemes

w = w1 = w2 = w3 = w = 5

def time() :
    frame = 0.04
    for i, start_time in enumerate(tlist) :
        end_time = tlist[i]
        frame = frame * (i + 1)
        poly = poly_coeff(start_time, end_time, frame)
        Newton(poly) 

def poly_coeff(stime, etime, f) :
    """The equation is k6 * u^3 + k5 * u^2 + k4 * u + k0 = 0. Computing the coefficients for this polynomial."""
    """Substituting the required values we get the coefficients."""
    t_u = f
    t0 = stime
    t3 = etime
    t1 = t2 = (stime + etime) / 2
    w0 = w1 = w2 = w3 = w
    k0 = w0 * (t_u - t0)
    k1 = w1 * (t_u - t1)
    k2 = w2 * (t_u - t2)
    k3 = w3 * (t_u - t3)
    k4 = 3 * (k1 - k0)
    k5 = 3 * (k2 - 2 * k1 + k0)
    k6 = k3 - 3 * k2 + 3 * k1 -k0 

    return [[k6,3], [k5,2], [k4,1], [k0,0]]

def poly_differentiate(poly):
    """ Differentiate polynomial. """
    newlist = copy.deepcopy(poly)

    for term in newlist:
        term[0] *= term[1]
        term[1] -= 1

    return newlist

def poly_substitute(poly, x):
    """ Apply value to polynomial. """
    sum = 0.0 

    for term in poly:
        sum += term[0] * (x ** term[1])
    return sum

def Newton(poly):
    """ Returns a root of the polynomial"""
    poly_diff = poly_differentiate(poly) 
    counter = 0
    epsilon = 0.000000000001

    x = float(raw_input("Enter initial guess:"))

    while True:
        x_n = x - (float(poly_substitute(poly, x)) / poly_substitute(poly_diff, x))
        counter += 1
        if abs(x_n - x) < epsilon :
            break
        x = x_n
    print "Number of iterations:", counter
    print "The actual root is:", x_n
    return x_n

if __name__ == "__main__" :
    time()
Enter initial guess:0.5
Traceback (most recent call last):
  File "newton.py", line 79, in <module>
    time()
  File "newton.py", line 18, in time
    Newton(poly) 
  File "newton.py", line 67, in Newton
    x_n = x - (float(poly_substitute(poly, x)) / poly_substitute(poly_diff, x))
ZeroDivisionError: float division

3 个回答

0

乍一看

 poly_substitue(poly_diff,x) 

在某个特定的x值下,似乎结果是零。你可以在每次更新之前打印出x的值,来跟踪这个过程。

不过我觉得这个异常是因为你的代码里有个bug:在多项式中,绝对系数C*X^0的导数是0 * X^-1,当x等于0时,你的poly_substitute就会引发一个ZeroDivisionException(除以零的异常)。

3

我复制了你的代码,并尝试调试了一下。

总的来说,问题出在你的代码返回了一个零值,然后在进行除法运算时使用了这个零值。

如果你仔细检查你的代码,会发现下面这个循环:

for i, start_time in enumerate(tlist) :
        end_time = tlist[i]

在第一次运行时,start_time 和 endTime 都会等于 0.0。

这就导致了下面这一行:

poly = poly_coeff(start_time, end_time, frame)

返回了:

>>> [[0.0, 3], [0.0, 2], [0.0, 1], [0.2, 0]]

这就造成了:

poly_substitute(poly_diff, x)

在你使用下面这个循环时:

for term in poly:
    sum += term[0] * (x ** term[1])

返回了一个零,因为你只是在乘以零。

所以你试图在零上进行删除操作,结果就出现了你提到的异常。

这意味着如果你修改代码,安全地检查并将 endTime 设置为 tList[i+1],你就能消除这个错误——别忘了检查 'i+1'。

6

这里有一个基本的错误:

for i, start_time in enumerate(tlist):
    end_time = tlist[i]

因为enumerate的特性,start_timeend_time的值是一样的。这就导致poly_coeff每次都会返回[[0,3], [0,2], [0,1], [0,0]]。当这个结果通过Newton传递给poly_differentiate时,结果会变成[[0,2], [0,1], [0,0], [0,-1]]

这个结果再传给poly_substitute时,会得到一个总和为零的结果,因为你在求和之前把所有列表中的值都乘以term[0](而term[0]恰好是零)。然后,你就会出现除以零的情况。

解决方案(根据你的评论进行了修改)

使用正确的start_timeend_time值。看起来你想要的是end_time = tlist[i+1]。这个边界条件是为了在不评估最后一个列表项的情况下退出。你真正想要的是这个:

for i, start_time in enumerate(tlist[:-1]):
    end_time = tlist[i+1]

撰写回答