割圆术
国魏晋时期的数学家刘徽于公元263
年撰写《九章算术注》,其中就有数学史上著名的“割圆术”。刘徽形容他的“割圆术”说:割之弥细,所失弥少,割之又割,以至于不可割,则与圆合体,而无所失矣。这包含了求极限的思想。通过求圆内接正多边形的周长来近似求圆的周长,并使正多边形的周长无限接近圆的周长,进而求得较为精确的圆周率。
设圆半径为1
, 圆内接正6
边形边长也为1
, 可如下计算正12
边形的边长:
OC=OB2−BC2=1−(AB/2)2
AB=OD=OA=1
CD=1−OC
新的边长 AD
值为:
AD=AC2+CD2=(AB/2)2+CD2
import math
def cutting_circle(n): # n为分割次数
"""接收表示分割次数的整数n为参数,计算分割n次时正多边形的边数和圆周率值,返回边数和圆周率值"""
side_length = 1 # 初始边长
edges = 6 # 初始边数
for i in range(n):
a=math.sqrt(1-(side_length/2)**2)
b=1-a
side_length=math.sqrt((side_length/2)**2+b**2)
edges=edges*2
pi=side_length*edges/2
return edges, pi
if __name__ == '__main__':
times = int(input()) # 割圆次数
edges, pi=cutting_circle(times)
print(f'分割{times}次,边数为{edges},圆周率为{pi:.6f}')
print(f'math库中的圆周率常量值为{math.pi:.6f}')
无穷级数法
π
是个超越数,圆周率的超越性否定了化圆为方这种尺规作图精确求解问题的可能性。有趣的是,π
可以用无穷级数表示:
11−31+51−71+⋯=4π
左边的展式是一个无穷级数,被称为莱布尼茨级数(Leibniz
),这个级数收敛到 π/4
,它通常也被称为格雷戈里-莱布尼茨级数,用以纪念莱布尼茨同时代的天文学家兼数学家詹姆斯·格雷戈里。
def leibniz_of_pi(error):
f=-1
n=3
p=1
num=1
"""接收用户输入的浮点数阈值为参数,返回圆周率值"""
while p>=error:
num=num+f*(1/n)
n=n+2
f=-f
p=1/n
pi=num*4
return pi
if __name__ == '__main__':
threshold = float(input())
print("{:.8f}".format(leibniz_of_pi(threshold)))
用蒙特卡洛方法计算圆周率π的原理如下:一个边长为2r
的正方形内部相切一个半径为 r
的圆,圆的面积是πr2
,正方形的面积为4r2
,二者面积之比是π / 4
,因为比值与r
大小无关,所以可以假设半径r
的值为1
。
在这个正方形内部,随机产生n
个点,坐标为(x
, y
),当随机点较多时,可以认为这些点服从均匀分布的规律。计算每个点与中心点的距离是否小于圆的半径(x2+y2<r2)
,以此判断是否落在圆的内部。统计圆内的点数c
,c
与n
的比值乘以4
,就是π
的值。理论上,n
越大,计算的π
值越准,但由于随机数不能保证完全均匀分布,所以蒙特卡洛法每次计算结果可能不同。
import random
def monte_carlo_pi(num):
n=0
for i in range(num):
x, y = random.uniform(-1, 1), random.uniform(-1, 1)
if x**2+y**2<=1:
n=n+1
else:
n=n
m=n/num*4
return m
if __name__ == '__main__':
sd = int(input()) #读入随机数种子
random.seed(sd) #设置随机数种子
times = int(input()) # 输入正整数,表示产生点数量
print(monte_carlo_pi(times)) # 输出圆周率值,浮点数
1706
年,英国人 约翰·梅钦( John Machin
) 发明了一个用于计算π / 4
值的公式: 4π=4arctan51−arctan2391
梅钦公式是格里高利/莱布尼茨计算的公式的变体,但是更实用,它的收敛速度显著增加,这使得它成为了更实用的计算的方法,虽然有若干种类梅钦(Machin-like
)公式,但梅钦公式仍然是计算值的主要公式。
import math
def machin_of_pi():
num=4*math.atan(1/5)-math.atan(1/239)
pi=4*num
return pi
if __name__ == '__main__':
cal_pi = machin_of_pi() # 调用判断类型的函数
print(cal_pi) # 输出函数运行结果
拉马努金公式
拉马努金曾经提出过很多关于求π的公式,这些公式都有以下几个特点: 等号右边的构造超乎常人想象,收敛速度极快!
π1=980122∑k=0∞(k!)43964k(4k)!(1103+26390k)
import math
num=0
def ramanujan_of_pi(n):
for i in range(0,n):
num1=math.factorial(4*i)
num2=math.factorial(i)
num3=num1*(1103+26390*i)
num4=(num2**4)*(396**(4*i))
num5=num3/num4
num=num+num5
m=(2*math.sqrt(2)/9801)*num
pi=1/m
return pi
if __name__ == '__main__':
n = int(input())
cal_pi = ramanujan_of_pi(n)
print(cal_pi)