Бесконечная сумма с заданной точностью

#python

Вопрос:

Я пытался решить эту бесконечную сумму с заданной точностью. Вы можете увидеть описание на картинке ниже

Вот что я пробовал до сих пор:

 import math
def infin_sum(x, eps):
    sum = float(0)
    prev = ((-1)*(x**2))/2
    i = 2
    while True:
        current = prev   ((-1)**i) * (x**(2*i)) / math.factorial(2*i) 
        if(abs(current - prev) <= eps):
            print(current)
            return current
        prev = current
        i =1
 

Для данного ввода выборки (0,2 для x и точность 0,00001) моя сумма составляет 6,65777777777778 e-05, и, согласно их тестам, она недостаточно близка к правильному ответу

Комментарии:

1. Более стабильным способом его вычисления была бы сортировка по величине абс, а затем суммирование.

Ответ №1:

Вы должны использовать math.isclose() вместо abs() для проверки вашей сходимости (учитывая, что именно так будет проверяться результат). учитывая, что каждая итерация добавляет или вычитает определенный член, дельта между предыдущим и следующим (Si-1 против Si) будет равна последнему добавленному члену (поэтому вам не нужно отслеживать предыдущее значение).

Этот бесконечный ряд почти совпадает с косинусом (было бы так, если бы я начал с нуля), поэтому вы можете проверить свой результат math.cos(x)-1 . Кроме того, я нахожу странным, что проверка ожидаемого результата фиксируется с точностью до 0,0001, но ввод образца указывает точность 0,00001 (я предполагаю, что более точный результат будет в пределах 0,0001, но тогда проверка на самом деле не проверяет правильность вывода с учетом входных данных?)

 from math import isclose
def cosMinus1(x,precision=0.00001):
    result      = 0
    numerator   = 1
    denominator = 1
    even        = 0
    while not isclose(numerator/denominator,0,abs_tol=precision): # reach precision
        numerator   *= -x*x                     #  /- for even powers of x
        even         = 2
        denominator *= even * (even-1)          # factorial of even numbers
        result       = numerator / denominator  # sum of terms            
    return result

print(cosMinus1(0.2))
# -0.019933422222222226

import math
expected = math.cos(0.2)-1

print(expected, math.isclose(expected,cosMinus1(0.2),abs_tol=0.0001))
# -0.019933422158758374 True
 

Ответ №2:

Поскольку тень-не очень хорошая идея sum , у вас была правильная идея назвать ее current , но вы не инициализировали current float(0) ее и забыли подвести итог. Это ваш код с исправленными проблемами:

 def infin_sum(x, eps):
    current = float(0)
    prev = ((-1) * (x ** 2)) / 2
    i = 2
    while True:
        current = current   (((-1) ** i) * (x ** (2 * i))) / math.factorial(2 * i)
        if (abs(current - prev) <= eps):
            print(current)
            return current
        prev = current
        i  = 1
 

В качестве более общего замечания, печать внутри подобной функции, вероятно, не лучшая идея — это ограничивает возможность повторного использования функции — в идеале вы хотели бы захватить возвращаемое значение и распечатать его вне функции.

Комментарии:

1. Я думаю, что мы оба совершили здесь ошибку. Сумма начинается с i = 1, и в моем коде prev в основном является первым элементом суммы. Поэтому я думаю, что нам нужно добавить случай, когда мы делаем current = prev (уравнение). Я добавил это в свой код, но все равно не работает :/

Ответ №3:

Во-первых, вы не суммируете элементы.

Пересчитывать все с нуля очень расточительно, а точность float s ограничена.

Вы можете использовать метод Хорнера для уточнения суммы:

  import math                                    

 def infin_sum(x, eps):                                   
     total = float(0)                                     
     e = 1                                                
     total = 0                                            
     i = 1                                                
     while abs(e) >= eps:                                 
         diff = (-1) * (x ** 2) / (2 * i) / (2 * i - 1)   
                                                          
         e *= diff                                        
         total  = e                                       
         i  = 1                                           
                                                          
     return total                                                                       
                                                   
                                                   
 if __name__ == "__main__":                        
     x = infin_sum(0.2, 0.00001)                   
     print(x)                                      
 

Ответ №4:

Не забудьте добавить результат, а не заменять его:

 prev  = current
 

вместо

 prev = current