自学-python-3 π的计算
本帖最后由 se6cxpp 于 2021-4-2 12:20 编辑编写初衷是看到了这么一句话
“圆周率一般用希腊字母π表示。它是一个无限不循环小数,目前已经计算出小数点后几十万亿位。既然小数点后有无穷多数字,那么一定有无穷多的数字组合。你有没有想过圆周率中是否有自己的生日数字组合或者QQ号组合和手机号组合?这个数字组合在什么位置?”
就是想看看自己的生日在π小数位的多少位,于是就开始了....
一、解决π的计算
通过查找找到一个公式
泰勒级数转换:
π/4=1-1/3+1/5-1/7+1/9...
这种还是好写的直接for循环控制循环次数就行
pi=0
for i in range(5000):
if i%2==0:
pi=pi+1/(2*i+1)
else:
pi=pi-1/(2*i+1)
print(pi*4)
算出的结果很是尴尬,因为循环100以内得到的数值和π还是有差距的,主要是因为公式的精度,于是继续找
Nilakantha 级数转换:
π = 3 + 4/(2*3*4) - 4/(4*5*6) + 4/(6*7*8) - 4/(8*9*10) + 4/(10*11*12) - 4/(12*13*14)...
pi=0
for i in range(5):
if i%2==0:
pi=pi+4/((2*i+2)*(2*i+3)*(2*i+4))
else:
pi=pi-4/((2*i+2)*(2*i+3)*(2*i+4))
print(pi+3)
这个就好多了,但是对于追求完美的我,继续找到了另一个公式
莱布尼兹转换
pi=0
for i in range(5):
if i%2==0:
pi=pi+(1/(2*i+1))*((1/2**(2*i+1))+(1/3**(2*i+1)))
else:
pi=pi-(1/(2*i+1))*((1/2**(2*i+1))+(1/3**(2*i+1)))
print(pi*4)
这种算法使得极度收敛到π
三种方法对比
x=int(input("输入计算次数:"))
pi1=0
for i in range(x):
if i%2==0:
pi1=pi1+1/(2*i+1)
else:
pi1=pi1-1/(2*i+1)
print("泰勒级数转换结果",pi1*4)
pi3=0
for i in range(x):
if i%2==0:
pi3=pi3+4/((2*i+2)*(2*i+3)*(2*i+4))
else:
pi3=pi3-4/((2*i+2)*(2*i+3)*(2*i+4))
print("Nilakantha级数转换结果",pi3+3)
pi2=0
for i in range(x):
if i%2==0:
pi2=pi2+(1/(2*i+1))*((1/2**(2*i+1))+(1/3**(2*i+1)))
else:
pi2=pi2-(1/(2*i+1))*((1/2**(2*i+1))+(1/3**(2*i+1)))
print("莱布尼茨级数转换",pi2*4)
大家可以看看结果
同时提供一个运算精度的比较
x=int(input("输入计算次数:"))
pi1=0
for i in range(x):
if i%2==0:
pi1=pi1+1/(2*i+1)
else:
pi1=pi1-1/(2*i+1)
pi2=0
for i in range(x):
if i%2==0:
pi2=pi2+(1/(2*i+1))*((1/2**(2*i+1))+(1/3**(2*i+1)))
else:
pi2=pi2-(1/(2*i+1))*((1/2**(2*i+1))+(1/3**(2*i+1)))
pi3=0
for i in range(x):
if i%2==0:
pi3=pi3+4/((2*i+2)*(2*i+3)*(2*i+4))
else:
pi3=pi3-4/((2*i+2)*(2*i+3)*(2*i+4))
result1="泰勒级数转换结果"
result2="莱布尼茨级数转换结果"
result3="Nilakantha级数转换结果"
a=pi1*4
b=pi2*4
c=pi3+3
d=3.14159265358979323846264338327950288419716939937510 # 标准值(小数后50位)
print(result1.rjust(16,"*"),":","{:.50f}".format(a))
print(result2.rjust(14,"*"),":","{:.50f}".format(b))
print(result3.rjust(18,"*"),":","{:.50f}".format(c))
m1=1-(abs(a-d)/d) # abs()返回一个数的绝对值
m2=1-(abs(b-d)/d)
m3=1-(abs(c-d)/d)
print(m1)
print(m2)
print(m3)
这个就很直观了
解决了π的运算,发现小数位并不能到很多位
即使用format规定50位,16位以后也是用0填充,很尴尬
于是找到了decimal模块
先看个小例子
根号2的计算
from decimal import* # 十进制函数
getcontext().prec=500 # 控制小数位数
print(Decimal('2').sqrt(),"\n") #计算根号2
print(Decimal(2).sqrt()) #计算根号2
通过这种方法
改写(用到一点定义函数)
贝拉公式计算
from decimal import *
def bbp(n):
pi=Decimal(0)
k=0
while k<=n:
pi+=(Decimal(1)/(16**k))*((Decimal(4)/(8*k+1))-(Decimal(2)/(8*k+4))-(Decimal(1)/(8*k+5))-(Decimal(1)/(8*k+6)))
k+=1
return pi
getcontext().prec=(1000)
print(bbp(50))
成功实现
加入查找行
from decimal import *
m=input("输入运算精度(默认为10):") or "10"
n=input("输入保留有效数字(默认为10):") or "10"
def pi(x):
pi=Decimal(0)
k=0
while k<=x:
pi+=(Decimal(1)/(16**k))*((Decimal(4)/(8*k+1))-(Decimal(2)/(8*k+4))-(Decimal(1)/(8*k+5))-(Decimal(1)/(8*k+6)))
k+=1
return pi
getcontext().prec=(int(n))
print(pi(int(m)))
y=input("输入生日日期(如2月14日(默认)输入:0214):") or "0214"
while True:
try:
print("从结果的第",str(pi(int(m))).index(y),"位找到结果")
break
except:
print("未找到")
break
搞定
学习了,谢谢楼主!! 脑洞好大。棒棒哒 太溜了,我最近也准备自学这个,请给点学习建议!
谢谢大神! 脑洞好大!厉害 不仅学到了几种π的级数求法,也学到了Python的简单编程,不错不错 谢谢楼主分享!!! 输入默认的0214都是没找到
Loganaahhh 发表于 2021-4-2 16:20
输入默认的0214都是没找到
大概在四千多位,运算精度默认10有效数字输入5000。
很好的经验。有了Python的基本功,还得搭上其他技术技能才行。
页:
[1]
2