Почему вычисление значения числа пи с использованием формулы Мачина дает неправильное значение?

Для моего школьного проекта я пытался вычислить ценность использования различных методов. Одна из формул, которую я нашел, была Формула Мачина, которую можно вычислить, используя разложение Тейлора арктана (x).

Я написал следующий код на Python:

import decimal

count = pi = a = b = c = d = val1 = val2 = decimal.Decimal(0) #Initializing the variables      
decimal.getcontext().prec = 25 #Setting percision

while (decimal.Decimal(count) <= decimal.Decimal(100)): 
    a = pow(decimal.Decimal(-1), decimal.Decimal(count))
    b = ((decimal.Decimal(2) * decimal.Decimal(count)) + decimal.Decimal(1))
    c = pow(decimal.Decimal(1/5), decimal.Decimal(b))
    d = (decimal.Decimal(a) / decimal.Decimal(b)) * decimal.Decimal(c)
    val1 = decimal.Decimal(val1) + decimal.Decimal(d)
    count = decimal.Decimal(count) + decimal.Decimal(1)
    #The series has been divided into multiple small parts to reduce confusion

count = a = b = c = d = decimal.Decimal(0) #Resetting the variables

while (decimal.Decimal(count) <= decimal.Decimal(10)):
    a = pow(decimal.Decimal(-1), decimal.Decimal(count))
    b = ((decimal.Decimal(2) * decimal.Decimal(count)) + decimal.Decimal(1))
    c = pow(decimal.Decimal(1/239), decimal.Decimal(b))
    d = (decimal.Decimal(a) / decimal.Decimal(b)) * decimal.Decimal(c)
    val2 = decimal.Decimal(val2) + decimal.Decimal(d)
    count = decimal.Decimal(count) + decimal.Decimal(1)
    #The series has been divided into multiple small parts to reduce confusion

pi = (decimal.Decimal(16) * decimal.Decimal(val1)) - (decimal.Decimal(4) * decimal.Decimal(val2))
print(pi)

Проблема в том, что я получаю правильное значение числа Пи только до 15 знаков после запятой, независимо от того, сколько раз цикл повторяется.

Например:

на 11 повторений первого цикла

pi = 3,141592653589793408632493

при 100 повторениях первого цикла

pi = 3,141592653589793410703296

Я не увеличиваю количество повторений второго цикла, так как arctan(1/239) очень мала и достигает очень малого значения с несколькими повторениями, и поэтому не должна влиять на значение pi только в 15 десятичных разрядах.

ДОПОЛНИТЕЛЬНАЯ ИНФОРМАЦИЯ:

Формула Мачина утверждает, что:

   π = (16 * Summation of (((-1)^n) / 2n+1) * ((1/5)^(2n+1))) - (4 * Summation of (((-1)^n) / 2n+1) * ((1/239)^(2n+1)))    

1 ответ

Решение

Этого количества терминов достаточно, чтобы получить более 50 знаков после запятой. Проблема заключается в том, что вы смешиваете поплавки Python с десятичными числами, поэтому ваши вычисления загрязняются ошибками в этих числах, которые имеют точность только до 53 бит (около 15 десятичных цифр).

Вы можете исправить это, изменив

c = pow(decimal.Decimal(1/5), decimal.Decimal(b))

в

c = pow(1 / decimal.Decimal(5), decimal.Decimal(b))

или же

c = pow(decimal.Decimal(5), decimal.Decimal(-b))

Очевидно, что аналогичное изменение должно быть сделано для

c = pow(decimal.Decimal(1/239), decimal.Decimal(b))

Вы могли бы сделать свой код намного более читабельным. Для начала вы должны поместить материал, вычисляющий ряд арктанов, в функцию, а не дублировать его для арктана (1/5) и арктана (1/239).

Кроме того, вам не нужно использовать десятичный для всего. Вы можете просто использовать простые числа Python для таких вещей, как count а также a, Например, ваш расчет для a можно записать как

a = (-1) ** count

или вы могли бы просто установить a 1 за пределами цикла и отрицайте его каждый раз через цикл.

Вот более компактная версия вашего кода.

import decimal

decimal.getcontext().prec = 60 #Setting precision

def arccot(n, terms):
    base = 1 / decimal.Decimal(n)
    result = 0
    sign = 1
    for b in range(1, 2*terms, 2):
        result += sign * (base ** b) / b
        sign = -sign
    return result

pi = 16 * arccot(5, 50) - 4 * arccot(239, 11)
print(pi)

выход

3.14159265358979323846264338327950288419716939937510582094048

Последние 4 цифры - мусор, а остальные в порядке.

Другие вопросы по тегам