计算圆周率的五种方法

目录

割圆法

相关知识

割圆术

编程要求

代码实现

无穷级数法

编程要求

代码实现

蒙特卡洛法

蒙特卡洛法

随机数种子

编程要求

代码实现

梅钦法

梅钦公式

编程要求

代码实现

拉马努金法

拉马努金公式

编程要求

代码实现


割圆法

相关知识

割圆术

国魏晋时期的数学家刘徽于公元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​

编程要求

根据提示,在右侧编辑区补充代码,编程实现割圆法计算圆周率,输出在正六边形基础上分割n次时得到多边形的边数、圆周率值以及math库中的圆周率值。

代码实现

import math

def cutting_circle(n):      # n为分割次数
   
    side_length = 1  # 初始边长
    edges = 6  # 初始边数
   
    def length(x):    #x为AB
        h = math.sqrt(1-(x /2)**2)     # h为OC
        return math.sqrt((x /2)**2 + (1-h)**2)
    for i in range(n):
        side_length = length(side_length)
        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}')

测试说明

平台会对你编写的代码进行测试:

输入格式 输入为一行,一个正整数n ,表示在内接正六边形的基础上割圆的次数。

输出格式 输出为两行,第一行输出在内接正六边形基础上再次分隔n次,分隔得到的正多边形的边数m,以及割圆法计算得到的圆周率pi(保留六位小数);第二行输出math库里的pi值(保留六位小数)。 具体输出格式见示例。

示例 输入: 4 输出: 分割4次,边数为96,圆周率为3.141032 math库中的圆周率常量值为3.141593

无穷级数法

π 是个超越数,圆周率的超越性否定了化圆为方这种尺规作图精确求解问题的可能性。有趣的是,π 可以用无穷级数表示:

11​−31​+51​−71​+⋯=4π​

左边的展式是一个无穷级数,被称为莱布尼茨级数(Leibniz),这个级数收敛到 π/4,它通常也被称为格雷戈里-莱布尼茨级数,用以纪念莱布尼茨同时代的天文学家兼数学家詹姆斯·格雷戈里。

编程要求

根据提示,在右侧编辑区补充代码,编程用莱布尼茨级数计算 π值。输入一个较小的数作为阈值,当最后一项的绝对值小于给定阈值时停止计算并输出得到的 π 值。

代码实现

def leibniz_of_pi(error):
    """接收用户输入的浮点数阈值为参数,返回圆周率值"""
    # 补充你的代码
    f = 1
    i = 1
    result = 0    # 初始化
    while 1 / (2 * i - 1) >= error:
        result += f * 1 / (2 * i - 1)
        f = -f
        i += 1
    return result * 4

if __name__ == '__main__':
    threshold = float(input())
    print("{:.8f}".format( leibniz_of_pi(threshold)  ) ) #保留小数点后八位

测试说明

平台会对你编写的代码进行测试: 输入格式 输入为一行,一个正浮点数 threshold,用以限定级数法求解 pi 值时,迭代累加只加绝对值大于 threshold 的项。

输出格式 输出为一个浮点数,是程序使用级数法求解的 pi 值,要求保留小数点后八位。

输入输出示例

示例 1

输入: 0.000002 输出: 3.14158865

示例 2

输入: 1e-6 输出: 3.14159065

蒙特卡洛法

蒙特卡洛法

蒙特卡洛(Monte Carlo)方法是由数学家冯·诺伊曼提出的,诞生于上世纪40年代美国的“曼哈顿计划”。蒙特卡洛是一个地名,位于赌城摩纳哥,象征概率。蒙特卡洛方法的原理是通过大量随机样本,去了解一个系统,进而得到所要计算的值。

用蒙特卡洛方法计算圆周率π的原理如下:一个边长为2r 的正方形内部相切一个半径为 r 的圆,圆的面积是πr2,正方形的面积为4r2二者面积之比是π / 4,因为比值与r大小无关,所以可以假设半径r的值为1

图片

在这个正方形内部,随机产生n个点,坐标为(x, y),当随机点较多时,可以认为这些点服从均匀分布的规律。计算每个点与中心点的距离是否小于圆的半径(x2+y2<r2),以此判断是否落在圆的内部。统计圆内的点数ccn的比值乘以4,就是π的值。理论上,n越大,计算的π值越准,但由于随机数不能保证完全均匀分布,所以蒙特卡洛法每次计算结果可能不同。

随机数种子

计算机中的随机数是通过算法产生,相同的随机数种子可以帮助我们获得相同的随机数序列,所以自动评测的题目都要求使用随机数种子。本题中只需要执行以下语句就可以。

  1. sd = int(input()) # 读入随机数种子
  2. random.seed(sd) # 设置随机数种子

编程要求

根据提示,在右侧编辑器补充代码,编程实现用蒙特卡洛方法计算π值,为了自动测评的需要,请先读入一个正整数sd作为随机数种子,并要求使用下面语句来生成随机点的坐标值: x, y = random.uniform(-1, 1), random.uniform(-1, 1)

代码实现

import random

def monte_carlo_pi(num):
    """接收正整数为参数,表示随机点的数量,利用蒙特卡洛方法计算圆周率
    返回值为表示圆周率的浮点数"""
   
    c = 0
    for _ in range(num): 
     x, y = random.uniform(-1, 1), random.uniform(-1, 1)
     if x * x + y * y <= 1:
           c += 1
    time = c * 4 / num
    return time
   

if __name__ == '__main__':
    sd = int(input())             #读入随机数种子
    random.seed(sd)               #设置随机数种子
    times = int(input())          # 输入正整数,表示产生点数量
    print(monte_carlo_pi(times))  # 输出圆周率值,浮点数

测试说明

平台会对你编写的代码进行测试:

** 示例 ** 输入: 100 100000 输出: 3.15316

梅钦法

梅钦公式

1706 年,英国人 约翰·梅钦( John Machin) 发明了一个用于计算π / 4值的公式: 4π​=4arctan51​−arctan2391​ 梅钦公式是格里高利/莱布尼茨计算的公式的变体,但是更实用,它的收敛速度显著增加,这使得它成为了更实用的计算的方法,虽然有若干种类梅钦(Machin-like)公式,但梅钦公式仍然是计算值的主要公式。

编程要求

根据提示,在右侧编辑器补充代码,计算并输出圆周率的大小。

代码实现

from math import*

def machin_of_pi():
    """用梅钦级数计算圆周率,返回圆周率值"""
    # 补充你的代码
    pi = 4 * (4 * atan(1 / 5) - atan(1 / 239))
    return pi
    
if __name__ == '__main__':
    cal_pi = machin_of_pi()  # 调用判断类型的函数
    print(cal_pi)            # 输出函数运行结果

测试说明

平台会对你编写的代码进行测试:

输入: 无 输出: 3.1415926535897936

拉马努金法

拉马努金公式

拉马努金曾经提出过很多关于求π的公式,这些公式都有以下几个特点: 等号右边的构造超乎常人想象,收敛速度极快!

π1​=980122​​∑k=0∞​(k!)43964k(4k)!(1103+26390k)​

输入一个正整数 n,根据些公式计算累加 n 次时的圆周率值。

编程要求

根据提示,在右侧编辑器补充代码,调用math库中的阶乘函数计算并输出圆周率的大小。

代码实现

from math import*

def ramanujan_of_pi(n):
    """接收一个正整数n为参数,用拉马努金公式的前n项计算圆周率并返回。"""
    # 补充你的代码
    c = 0
    b = 2 * sqrt(2) / 9801
    for i in range(n):
        a = pow(factorial(i),4) * pow(396,4 * i)   # 分母
        c += (factorial(4 * i) * (1103 + 26390 * i)) / a
       
    pi = 1 / (b * c)

    return pi

if __name__ == '__main__':
    n = int(input())                
    cal_pi = ramanujan_of_pi(n)  
    print(cal_pi)                    # 输出函数运行结果

测试说明

平台会对你编写的代码进行测试:

测试输入: 1 预期输出: 3.1415927300133055

  • 41
    点赞
  • 50
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值