У меня есть этот код для решения метода Ньютона. Но он дает ошибку с нулевым делением. Я не могу понять, что не так. Спасибо.
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
У вас есть основная ошибка здесь:
for i, start_time in enumerate(tlist):
end_time = tlist[i]
Из-за природы enumerate
, start_time
и end_time
имеют одинаковое значение. Это означает, что poly_coeff
будет возвращать [[0,3], [0,2], [0,1], [0,0]]
каждый раз. Когда этот результат передается (через Newton
) в poly_differentiate
, результат будет [[0,2], [0,1], [0,0], [0,-1]]
.
Этот результат, переданный в poly_substitute
, даст сумму ZERO, потому что перед их суммированием вы умножаете все записи списка по term[0]
(который оказывается равным нулю). Затем вы делите - на ноль.
РЕШЕНИЕ (отредактировано за ваш комментарий):
Используйте правильные значения start_time
и end_time
. Похоже, вы хотите end_time = tlist[i+1]
. Крайнее условие этого состоит в том, чтобы выйти из строя, не оценивая конечную запись в списке. Что вы действительно хотите, так это:
for i, start_time in enumerate(tlist[:-1]):
end_time = tlist[i+1]
Я скопировал ваш код и немного пытался его отладить.
В общем, это потому, что ваш код возвращает нулевое значение, а затем попытался использовать его во время деления.
Если вы внимательно просмотрите свой код, вы увидите, что следующий цикл:
for i, start_time in enumerate(tlist) :
end_time = tlist[i]
даст вам start_time == 0.0 и 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])
чтобы вернуть вам нуль, так как вы умножаете только нули.
Итак, вы пытаетесь удалить на 0 и получить указанное исключение.
Это означает, что если вы измените свой код, чтобы безопасно проверить и установить endTime в tList [i + 1], вы устраните эту ошибку - не забудьте проверить "i + 1"
На первый взгляд
poly_substitue(poly_diff,x)
представляется для нуля равным нулю. Попробуйте отследить итерацию, напечатав x перед каждым обновлением.
Но я думаю, что исключение вызвано ошибкой в вашем коде: поскольку абсолютный коэффициент C * X ^ 0 в полиноме дифференцируется на 0 * X ^ -1, ваш poly_substitute
вызывает ZeroDivisionException
при x = 0.