为什么使用 Machin 公式计算 pi 的值会给出错误的值?
Why is the computing of the value of pi using the Machin Formula giving a wrong value?
对于我的学校项目,我试图计算使用不同方法的价值。我找到的公式之一是 Machin 公式,它可以使用 arctan(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)
问题是我得到的 pi 的正确值只保留到小数点后 15 位,无论循环重复多少次。
例如:
第一个循环重复 11 次
pi = 3.141592653589793408632493
第一个循环重复 100 次
pi = 3.141592653589793410703296
我没有增加第二个循环的重复次数,因为 arctan(1/239) 非常小,重复几次就达到了一个极小的值,因此应该不会影响仅小数点后 15 位的 pi 值。
额外信息:
Machin 公式指出:
π = (16 * Summation of (((-1)^n) / 2n+1) * ((1/5)^(2n+1))) - (4 * Summation of (((-1)^n) / 2n+1) * ((1/239)^(2n+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))
您可以使您的代码 很多 更具可读性。对于初学者,您应该将计算 arctan 级数的东西放入一个函数中,而不是为 arctan(1/5) 和 arctan(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位是垃圾,但其余的都很好。
对于我的学校项目,我试图计算使用不同方法的价值。我找到的公式之一是 Machin 公式,它可以使用 arctan(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)
问题是我得到的 pi 的正确值只保留到小数点后 15 位,无论循环重复多少次。
例如:
第一个循环重复 11 次
pi = 3.141592653589793408632493
第一个循环重复 100 次
pi = 3.141592653589793410703296
我没有增加第二个循环的重复次数,因为 arctan(1/239) 非常小,重复几次就达到了一个极小的值,因此应该不会影响仅小数点后 15 位的 pi 值。
额外信息:
Machin 公式指出:
π = (16 * Summation of (((-1)^n) / 2n+1) * ((1/5)^(2n+1))) - (4 * Summation of (((-1)^n) / 2n+1) * ((1/239)^(2n+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))
您可以使您的代码 很多 更具可读性。对于初学者,您应该将计算 arctan 级数的东西放入一个函数中,而不是为 arctan(1/5) 和 arctan(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位是垃圾,但其余的都很好。