Top.Mail.Ru
Ответы

Неправильно считается сумма ряда в Python

Пишу программу для расчета значения интегрального косинуса (функция стремится к 0 при x, стремящемся к бесконечности), а для этого нужно вычислить сумму сходящегося на всей оси x ряда. Если x меньше 67, то вроде всё нормально считает, даже график функции такой, какой и должен быть, но когда x превышает это значение, сумма ряда и, соответственно, значение функции начинает резко расти до неадекватных размеров, хотя так вроде быть не должно.
Почему так происходит?
Код для вычисления значения функции:
import math
from decimal import Decimal
EULER = Decimal(0.5772156649015328606)

def fact(n):
factorial = Decimal(1)
while Decimal(n) > 1:
factorial *= n
n -= Decimal(1)
return Decimal(factorial)

def ryad(z):
x = Decimal(z)
EPS = Decimal(1e-10)
S = Decimal(0)
a = Decimal(1)
n = Decimal(1)
while Decimal(math.fabs(a)) > EPS:
e0 = Decimal((-1)**n)
e1 = Decimal(x**(2*n))
e2 = Decimal(2*n)
e3 = fact(2*n)
a = (e0*e1)/(e2*e3)
print(f"На {n} шаге a = {a}")
n += Decimal(1)
S += a
print(f"На {n} шаге S = {S}")
print(a)
print(f"Сумма ряда равна {S}")
return S
c = float(input("Введите значение x: "))
print(f"Значение Ci(x)= {float(EULER)+float(ryad(c))+math.log(c)}")

Дополнен

Не заметил, как отступы при копировании исяезли, вот исправленный вариант:
def fact(n):
factorial = Decimal(1)
while Decimal(n) > 1:
factorial *= n
n -= Decimal(1)
return Decimal(factorial)
def ryad(z):
x = Decimal(z)
EPS = Decimal(1e-10)
S = Decimal(0)
a = Decimal(1)
n = Decimal(1)
while Decimal(math.fabs(a)) > EPS:
e0 = Decimal((-1)**n)
e1 = Decimal(x**(2*n))
e2 = Decimal(2*n)
e3 = fact(2*n)
a = (e0*e1)/(e2*e3)
#print(f"На {n} шаге a = {a}") n += Decimal(1)
#S += a print(f"На {n} шаге S = {S}")
#print(a)
#print(f"Сумма ряда равна {S}")
return S
c = float(input("Введите значение x: "))
print(f"Значение Ci(x)= {float(EULER)+float(ryad(c))+math.log(c)}")

Дополнен

Сайт отступы убирает, не получается код нормально записать, поэтому пришлось скриншоты делать

Только авторизированные пользователи могут оставлять свои ответы
Дата
Популярность
Аватар пользователя
Новичок

Самый простой способ решения проблемы - просто увеличить точность Decimal:

12
 from decimal import * 
getcontext().prec = 4096 

Сайт НЕ убивает отступы, если ты пользуешься кнопочкой <> в редакторе - специально предназначенной для публикации кода.

Аватар пользователя
Оракул
1234
 Напиши
    Нормально
        Код
            С отступами 
Аватар пользователя
Оракул

Python - язык чувствительный к отступам. Вы серьезно рассчитываете что кто-то возьмется за дебаг этого полотна простого текста? Ставьте блок кода для начала.

Сайт никуда ничего не убирает. Ещё раз: >>>БЛОК КОДА!<<<

Аватар пользователя
Просветленный

Проблема, которую вы описываете, скорее всего, связана с потерей точности в вычислениях из-за очень больших или очень маленьких чисел, а также из-за накопления ошибок округления при работе с числами с плавающей запятой. Когда x становится достаточно большим, значения факториалов в знаменателе ряда становятся настолько большими, что даже Decimal может не справляться с точным представлением этих чисел.

Для улучшения точности вычислений в вашем коде можно предпринять несколько шагов:

Используйте более точное представление чисел: Вы уже используете Decimal, что является хорошим выбором. Убедитесь, что точность Decimal достаточно высока для ваших расчетов.

Пересмотрите алгоритм вычисления факториала: Для очень больших чисел вычисление факториала может привести к очень большим числам, что вызовет потерю точности. Можно попробовать использовать аппроксимации, например, формулу Стирлинга, для оценки факториалов больших чисел.

Анализируйте поведение ряда: Убедитесь, что ваш ряд действительно сходится при больших значениях x. Возможно, потребуется более тщательный анализ для определения поведения ряда в этих условиях.

Проверка условия выхода из цикла: Убедитесь, что условие выхода из цикла while Decimal(math.fabs(a)) > EPS корректно работает для больших x. Может быть полезно добавить дополнительные условия для ограничения максимального количества итераций.

Оптимизация вычислений: Поскольку вычисления в знаменателе включают возведение в степень и факториал, которые могут быть очень затратными, рассмотрите возможность оптимизации этих вычислений.

Да