栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

割圆术计算圆周率

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

割圆术计算圆周率

文章目录
  • 前言
  • 一、割圆术简介
  • 二、原理
  • 三、算法实现
  • 四、实例代码
    • Java I
    • Java II
    • Python
  • 总结


前言

计算圆周率有多种算法,其中割圆术是中国最早的一种算法,理解简单,适合入门。而随着计算机、数学的发展,人们发明了更高效的算法,计算机也帮助人们将圆周率计算至小数点后 3.14 万亿位。


一、割圆术简介

割之弥细,所失弥少,割之又割,以至于不可割,则与圆合体,而无所失矣。

——刘徽

所谓“割圆术”(cyclotomic method),是用圆内接正多边形的面积去无限逼近圆面积并以此求取圆周率的方法。
参考:百度百科——割圆术

二、原理

如图所示,根据圆的面积公式 S = π r 2 S=pi r^2 S=πr2 可知,当圆的半径为 1 时,圆的面积等于 π,所以我们可以算半径为 1 的正多边形的面积,即可得到近似的 π。观察图像,S圆 > S正24边形 > S正12边形 > S正6边形,所以我们的计算结果的精确度随边的个数的增加而提高,但始终小于 S圆,即始终小于 π。

三、算法实现

如图,
S △ A O B = 1 2 r 2 sin ⁡ 6 0 ∘ S_{triangle AOB}=frac12r^2sin60^circ S△AOB​=21​r2sin60∘
S △ A O C = 1 2 r 2 sin ⁡ 3 0 ∘ S_{triangle AOC}=frac12r^2sin30^circ S△AOC​=21​r2sin30∘
S △ A O D = 1 2 r 2 sin ⁡ 1 5 ∘ S_{triangle AOD}=frac12r^2sin15^circ S△AOD​=21​r2sin15∘
… … …
S △ A O N = 1 2 r 2 sin ⁡ ∠ A O N S_{triangle AON}=frac12r^2sinangle AON S△AON​=21​r2sin∠AON,
而
S 正 六 边 形 = 6 S △ A O B = 3 sin ⁡ 6 0 ∘ = 3 3 2 S_{正六边形}=6S_{triangle AOB}=3sin60^circ=frac{3sqrt 3}2 S正六边形​=6S△AOB​=3sin60∘=233 ​​
S 正 十 二 边 形 = 12 S △ A O C = 6 sin ⁡ 3 0 ∘ = 3 sin ⁡ 6 0 ∘ cos ⁡ 3 0 ∘ S_{正十二边形}=12S_{triangle AOC}=6sin30^circ=frac{3sin60^circ}{cos30^circ} S正十二边形​=12S△AOC​=6sin30∘=cos30∘3sin60∘​
S 正 二 十 四 边 形 = 24 S △ A O D = 12 sin ⁡ 1 5 ∘ = 6 sin ⁡ 3 0 ∘ cos ⁡ 1 5 ∘ S_{正二十四边形}=24S_{triangle AOD}=12sin15^circ=frac{6sin30^circ}{cos15^circ} S正二十四边形​=24S△AOD​=12sin15∘=cos15∘6sin30∘​
… … …
S 正 3 ⋅ 2 n 边 形 = 3 ⋅ 2 n S △ A O N = 3 ⋅ 2 n − 1 sin ⁡ 6 0 ∘ 2 n − 1 = 3 ⋅ 2 n − 2 sin ⁡ 6 0 ∘ 2 n − 2 cos ⁡ 6 0 ∘ 2 n − 1 S_{正3cdot2^n边形}=3cdot2^nS_{triangle AON}=3cdot2^{n-1}sinfrac{60^circ}{2^{n-1}}=frac{3cdot2^{n-2}sinfrac{60^circ}{2^{n-2}}}{cosfrac{60^circ}{2^{n-1}}} S正3⋅2n边形​=3⋅2nS△AON​=3⋅2n−1sin2n−160∘​=cos2n−160∘​3⋅2n−2sin2n−260∘​​
我们不难发现,对于任意 n ( n ≥ 1 ) n(n≥1) n(n≥1),有:
S 正 3 ⋅ 2 n 边 形 = S 正 3 ⋅ 2 n − 1 边 形 cos ⁡ 6 0 ∘ 2 n − 1 S_{正3cdot2^n边形}=frac{S_{正3cdot2^{n-1}边形}}{cosfrac{60^circ}{2^{n-1}}} S正3⋅2n边形​=cos2n−160∘​S正3⋅2n−1边形​​
记 a n = cos ⁡ 6 0 ∘ 2 n − 1 a_n=cosfrac{60^circ}{2^{n-1}} an​=cos2n−160∘​,则 S 正 3 ⋅ 2 n 边 形 = S 正 六 边 形 ∏ i = 1 n a i S_{正3cdot2^n边形}=frac{S_{正六边形}}{prod_{i=1}^na_i} S正3⋅2n边形​=∏i=1n​ai​S正六边形​​。
所以,可以先计算 ∏ i = 1 n a i prod_{i=1}^na_i ∏i=1n​ai​,然后除 S 正 六 边 形 S_{正六边形} S正六边形​
而若用cos函数计算,则要用到 π,这无异于用结论算结论。而根据半角公式,可以得出 a n a_n an​的递推公式:
a n = a n − 1 + 1 2 a_n=sqrtfrac{a_{n-1}+1}{2} an​=2an−1​+1​ ​
所以程序如图:

四、实例代码 Java I
import java.util.Scanner;

public class Main {
	public static void main(String[] args){
		Scanner input=new Scanner(System.in);
		int n=input.nextInt(),i=1;
		double p=0.5,s=1;
		while(i<=n){
			p=Math.sqrt((p+1)/2);
			s=s*p;
			i++;
		}
		System.out.println(1.5*Math.sqrt(3)/s);
	}
}

结果:

99
3.141592653589794
Java II

该处使用了 java.math.BigDecimal 模块,以提高小数位数。

import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import java.util.Scanner;

public class Main {
	static MathContext mc = new MathContext(100, RoundingMode.HALF_UP); 		
	//BigDecimal开方
	public static BigDecimal sqrt(BigDecimal a) {
		BigDecimal _2=BigDecimal.valueOf(2.0);
		if(a.compareTo(BigDecimal.ZERO)==0)return BigDecimal.ZERO;
		else{
			BigDecimal x=a;
			int cnt=0;
			while(cnt<100){
				x=(x.add(a.divide(x,mc))).divide(_2,mc);
				cnt++;
			}
			return x;
		}
	}

	public static void main(String[] args){
		Scanner input=new Scanner(System.in);
		int n=input.nextInt(),i=1;
		BigDecimal p=new BigDecimal("0.5"),s=BigDecimal.ONE;
		while(i<=n){
			p=sqrt(p.add(BigDecimal.ONE).divide(new BigDecimal("2"),mc));
			s=s.multiply(p);
			i++;
		}
		System.out.println(sqrt(new BigDecimal("3")).multiply(new BigDecimal("1.5")).divide(s,mc));
	}
}

结果:(该算法精确至小数点后60位)

100
3.141592653589793238462643383279502884197169399375105820974944234988309941294683211597479745467855302
Python

该处用到了 decimal 库,精确度更高。

#!/usr/bin/python3
# -*- coding: utf-8 -*-
from decimal import *
getcontext().prec=256 #数字长度
n,i,c,s=input('请输入n: '),0,Decimal('0.5'),Decimal('1')
n=int(n)
while i 

结果:(该算法精确至小数点后 253 位)

请输入n: 1024
π约为: 3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117067982148086513282306647093844609550582231725359408128481117450284102701938521105559644622948954930381964428810975665933446128475648233786783165271201909145650

总结

文章结束,你应该掌握了割圆术,运用数学上的极限思维解决问题。对于圆周率的计算,目前已没多大实用意义,但这正是计算机技术进步的一个标尺。

声明:未经作者允许禁止转载。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/976713.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号