【算法】高精度计算π(pi)值

12 篇文章 8 订阅
订阅专栏

😀大家好,我是白晨,一个不是很能熬夜😫,但是也想日更的人✈。如果喜欢这篇文章,点个赞👍,关注一下👀白晨吧!你的支持就是我最大的动力!💪💪💪

在这里插入图片描述


📔前言


π π π 一直是一个备受数学界青睐的数字。从古至今,无数的学者都在努力探求着 π π π 精确值。🤼‍♂️从祖冲之到欧拉,📖从圣经到《数理精蕴》,从东至西,历经几千年的发展,特别是在计算机发明之后,对于 π π π 的求解可以说是一日千里,现在计算到几十亿位以后已经不值得惊讶。

🧐这篇文章,白晨想带大家去了解利用计算机求解 π π π 的一种方法,其中涉及到 C++,链表,大数四则运算等知识点。我会尽可能详细的讲解每一个难点的实现。

题目参考:

在这里插入图片描述

这次我们的最低目标是在3000ms的限制内,实现计算 π π π 到小数点后500位。


📕1.公式选择


首先,如果不清楚如何计算 π π π 的同学可以先参考下面的文章,有助于理解下面的公式选择。

π 是怎么算出来的?

相信大家看完后已经对 π π π 的求法有一定的认识了,所以这里给出几个关于 π π π 的几个公式:

在这里插入图片描述

我们这里选择第三个公式,为什么呢?

当然是因为第三个公式是题目给出的反正切函数的幂次展开式啦(bushi)

其实是因为第三个公式是线性收敛,平均每计算一次就会得到0.3个有效数字,相比于第四个 a r c t a n x arctanx arctanx泰勒展开公式(莱布尼茨公式)来说,效率上会高出很多,而且最重要的一点是它比较容易实现,递推公式如下:

在这里插入图片描述

将其展开就是第三个公式,大家可以对比着看。

关于 a r c t a n x arctanx arctanx泰勒展开计算 π π π 可以参考此篇文章: π的计算

反正切函数的幂次展开式的推导具体过程:

在这里插入图片描述


📗2.实现难点解析


  • 关于大数实现:

这里我们选择 C++ 模板中的 list 类来实现(也可以使用string类等,只要可以进行大数四则运算就可以,这里为了符合题意使用链表),由于 π π π 的整数部分为3,所以我们只需要一位来存储整数部分,也即front存储整数部分,其余小数点以后的位顺次向后连接。

我们的核心目标是要实现:

在这里插入图片描述

我们将上面的任务拆开,分解成一个个独立的任务

  • R ( n ) ∗ n R(n) * n R(n)n

这里我们选择模拟竖式乘法:

  • 从链表尾结点开始,每个结点的数乘n。
  • 结点中只能存放个位数,所以当乘得结果大于等于10,需要保存进位。
  • 每次计算乘法时,还需要加上前一个数的进位。
  • 循环上述过程,直到头节点。

在这里插入图片描述

  • R ( n ) ∗ n / ( 2 ∗ n + 1 ) R(n) * n/(2*n+1) R(n)n/2n+1

这里我们选择模拟竖式除法:

  • 用上面乘法得到的结果除以(2n + 1)。
  • 除法与乘法相反,我们要从头节点开始除法。
  • 每一位除以(2n + 1)得到的结果就是:(此节点的值 + 上一个结点的余数*10) /(2n + 1)。
  • 再保存这个结点除以(2n + 1)后所得的余数。
  • 循环上述过程,直到尾节点

此处不再演示,大家可以类比乘法动手模拟一下,其实非常相似,代码也很相似。

  • S u m ( n + 1 ) = S u m ( n ) + R ( n + 1 ) Sum(n + 1) = Sum(n) + R(n + 1) Sum(n+1)=Sum(n)+R(n+1)

这就是递推公式的最后一步,将上面计算得到的 R ( n + 1 ) R(n+1) R(n+1) 加到 S u m ( n ) Sum(n) Sum(n) 上,这其实就是一个大数加法的问题,我们选择模拟竖式加法:

  • 从最低位开始, R ( n + 1 ) R(n+1) R(n+1) S u m ( n ) Sum(n) Sum(n) 对应的位相加。
  • 相加得到的值如果大于等于10,需要进位。
  • 对应位相加得到的结果需要加上进位
  • 循环上述过程,直到头节点

此过程与乘法非常相近,在后面的代码实现中我们可以看出。

  • 关于链表结点个数

链表结点数代表着小数点后的位数,所以当然是结点越多越精确,但是结点数太多会影响性能。如果我们要实现500位的精确值,我的建议是创建550~600个结点即可。

  • 关于要迭代的次数

这里有两种根据所求精度估算大致的迭代的次数的方法:

  1. 估算精度

    int count(int n) 
    {
    	int i = 1;
    	double sum = 0;
    	int a, b;
    	while(1)
    	{
    		a = 2 * i + 1;
    		b = i;
    		sum = sum + log10(a / b);
    		i++;
    		if (sum > n + 1) {
    			return i;
    		}
    	}
    }
    

    参考文章: 数据结构实验1.2—高精度计算PI值(西工大)

  2. 估算有效数字

在这里插入图片描述

int count(int n)
{
	double ret = (double)n;
	return (int)(ret / 0.3);
}

参考文章: 目前求 π 的算法中哪种收敛最快?

以上两种方法都可以使用,根据我在release发布版本的测试下,两种方法没有数量级的差别,所以使用哪一种都可以。

注:如果要提升精度,必须也增大结点个数,不能只增加迭代次数

测试结果:

方法一:
在这里插入图片描述

方法二:
在这里插入图片描述


📘3.代码实现


#include <time.h>
#include <iostream>
#include <list>
#include<math.h>
using namespace std;

// 估测要计算的次数
// 方法一:
int count(int n) 
{
	int i = 1;
	double sum = 0;
	int a, b;
	while(1)
	{
		a = 2 * i + 1;
		b = i;
		sum = sum + log10(a / b);
		i++;
		if (sum > n + 1) {
			return i;
		}
	}
}

// 方法二:
int count(int n)
{
	double ret = (double)n;
	return (int)(ret / 0.3);
}

int main()
{
// 定义我们需要多少个结点
#define NODE_NUM 550
	list<int> num(NODE_NUM, 0);// 存放R(n)
	list<int> sum(NODE_NUM, 0);// 存放Sum(n)
	int print;// 所需精度
	cin >> print;
	int cnt = count(print);// 所需迭代次数
    
	// 我们直接将 R(1) 初始化为2,这样就可以免去后面再统一乘2
	num.front() = 2;
	sum.front() = 2;
	
	// 这里循环的 i 就是 n 
	for (int i = 1; i <= cnt; ++i)
	{			
		int ret = 0;// 记录进位,补位情况

	 // 计算R(n + 1)
	
		// 计算 R(n) * n
		for (list<int>::reverse_iterator cur1 = num.rbegin(); cur1 != num.rend(); cur1++)
		{
            // 每一位都是本位乘i,再加上进位
			int val = *cur1 * i + ret;
            // 保存进位
			ret = val / 10;
            // 保存本位
			*cur1 = val % 10;
		}

		ret = 0;
		// 计算 R(n) * n / (2n + 1)
		for (list<int>::iterator cur1 = num.begin(); cur1 != num.end(); cur1++)
		{
            // 除数
			int div = (i << 1) + 1;
            // 加上前一位的余数
			int val = *cur1 + ret * 10;
            // 除法,保存本位
			*cur1 = val / div;
            // 保存余数
			ret = val - *cur1 * div;
		}

		ret = 0;
		// 计算 sum += R(n + 1)
		for (auto cur2 = sum.rbegin(), cur1 = num.rbegin(); cur2 != sum.rend(); cur2++, cur1++)
		{
            // 大数加法
			int val = *cur1 + *cur2 + ret;
			*cur2 = val % 10;
			ret = val / 10;
		}
	
	}
	// 打印
	cout << sum.front() << '.';
	list<int>::iterator it = sum.begin();
	it++;

	int i = 0;
	while (i < print)
	{
		cout << *it;
		it++;
		i++;
	}
	
	return 0;
}

📙后记


这个方法其实还是有改进的细节,比如:

  1. 将输入输出更换为scanf和printf,因为其实在效率上 cin和cout 比前者慢了几十倍,在输出大型数字时,效率会受影响。
  2. 公式限制,其实比反正切幂次展开更高效的公式还是很多,这里只是为了实现简单和逻辑清晰而选择了反正切幂次展开,大家有兴趣可以参考下图公式自己去实现。

在这里插入图片描述

参考文章: 目前求 π 的算法中哪种收敛最快?


这是一个新的系列 ——【算法】,想来想去将这个计算 π π π 的文章放到了【算法】系列的开篇。因为其中确实有不少算法的实现,并且难度不是很大,很适合想学习C++或者算法的入门学习,在探求 π π π 的实践中一路学习高数🦄和编程(bushi)。

如果解析有不对之处还请指正,我会尽快修改,多谢大家的包容。

如果大家喜欢这个系列,还请大家多多支持啦😋!

如果这篇文章有帮到你,还请给我一个大拇指 👍和小星星 ⭐️支持一下白晨吧!喜欢白晨【算法】系列的话,不如关注👀白晨,以便看到最新更新哟!!!

我是不太能熬夜的白晨,我们下篇文章见。

π的计算
西风世界
09-11 2万+
说起圆周率的计算,估计很多人首先想到的是祖冲之的割圆术。确实,在当时的条件下,割圆术能将π计算到一个较高的精度,实在不易。 不过我们现在,希望使用计算机快速计算高精度π,这时我们该如何去做呢?算法库计算的思路像计算机中的数学库计算,一般都是采用泰勒展开进行的,像sin,cos这类的函数,都可以用泰勒展开式很方便的逼近。计算机计算的方法,就是用简单的多项式去不断逼近一个特殊的函数。
高精度计算PI C语言 思路,高精度计算pi
weixin_39689377的博客
05-21 1525
高精度计算PI题目描述​ 使用双向链表作为存储结构,请根据用户输入的一个整数(该整数表示精确到小数点后的位数,可能要求精确到小数点后 500 位),高精度计算PI。提示:可以利用反三角函数幂级展开式来进行计算。解题思路求PI算法​ 首先这道题是要求必须使用双向链表作为存储结构的,这个需要注意,而且也不能用数组计算完了之后挨个赋给链表的每个节点,这是耍赖 。​ ...
高精度计算PI C语言 思路,高精度计算PI
weixin_35225264的博客
05-21 1238
高精度计算PI高精度计算PI所用公式:#include #include typedef struct list{int data;struct list *next;struct list *pre;}list;list* Initlist(){list* head;head=(list*)malloc(sizeof(list));head->next=head->pre=hea...
高精度计算PI
Sekiro_2的博客
10-20 2284
实验1.2:高精度计算PI 所用公式: 在这里插入代码片 #include <stdio.h> #include <stdlib.h> typedef struct list{ int data; struct list *next; struct list *pre; }list; list* Initlist() { list* head; head=(list*)malloc(sizeof(list)); head-&g
c++高精度的计算π,可精确到n位
热门推荐
FreshMan
09-30 2万+
使用c++计算高精度π,其实就是一个数学的方法向c++语言转化的过程,下面将会展示: (1)选择计算公式:选取收敛速度快的且容易朝着的计算公式是首要的一环。我们选用: π/2=1+1/3+1/3*2/5+1/3*2/5*3/7……+1*2*3*……n/3*5*……*(2n+1) =1+1/3(1+2/5(1+……+(n-1)/(2n-1)(1+n/(2n+1))……); (2)确定输
pi 的计算 (高精度
05-14
pi 的计算 (高精度) 用pi 的几个近似计算公式算的,主要是使用了高精度
用数学方法求高精度pi
booniebears的博客
03-23 364
题意 用双向循环链表为存储结构解决高进度pi问题。pi要精确到第几位,就输出到第几位。 思路 首先给出我们计算pi的理论依据 行了,从这个结构上就可以看出来,要有两个链表,一个存放一项的(不断迭代),一个存放这些项的和(也不断迭代) 当然链表的每一个节点存放一个数位。其实用数组也是可以的。 既然是精度很高,那么肯定是要手动加减乘除了。 居然调了好几次才把这加减乘除搞定 代码 细节挺多,不一一说了。 //高精度计算PI #include <stdio.h> #include <stdl
C语言高精度PI
点滴
08-30 1万+
如下代码能求解出高精度PI #include #include long a=10000,b,c=2800,d,e,f[2801],g; int main() { for(;b-c;) f[b++]=a/5; for(;d=0,g=c*2;c-=14,printf("%.4ld",e+d/a),e=d%a) //原代码为%.4d,GCC给出警告.已改为%.4ld
高精度计算pi——参考后
GNC呼呼哒
04-20 984
高精度计算pi(参考后)问题参考原理代码 问题 问题如图,高精度计算pi用泰勒展开式计算。 参考 参考了大佬的代码后加了原理以及注释;大佬原文https://blog.csdn.net/zhao2018/article/details/79929881?utm_source=app&app_version=4.6.0 原理 1.由于计算的精度会达到很多位数,而浮点型数据最多位数32或64位,无法满足需求,则只能考虑自己建立一个元素组来计算,其中有整数部分,还有很多位数的小数部分。暂时考虑用链表
圆周率&pi;高精度快速计算器
03-16
这是一个可以快速精确求解圆周率Pi的小工具。给出所要求的小数位数精度,即可快速算出圆周率Pi小数点后数万位。其算法正确性可由泰勒级数、微积分和极限相关数学理论证明。 E-mail: hyk83@163.com
C++实现pi的任意精度计算
11-19
这是一份关于&pi;的任意精度计算的C++实现源代码.算法是基于二次收敛算法,即AGM(几何平均数)方法,该算法也可应用于计算椭圆积分和以先进的ADI算法实现椭圆偏微分方程. (速度可能优于Mathematica!!!)
PI的数学和计算机计算方法(C语言)
09-04
PI一直是数学家计算的对象,本文介绍如何利用计算机计算PI
C语言计算PI
06-15
这个是上课的时候编的一个小程序,用C语言计算PI,有问题请联系469406116
Calculate-pi:几种计算&pi;(pi)的算法
03-10
该存储库的目标是提出一些算法,使您可以高精度地计算&pi;。 为此,使用了模块。 该模块允许定义计算中使用的十进制数字。 显然,小数位数越多,by的计算所花费的时间就越长。 由于阶乘和平方根的计算需要很高的...
【C/C++项目】——高精度计算pi
最新发布
frank-liang的博客
06-01 1450
C++高精度计算pi
高精度高性能PI计算程序设计和验证
zhangfuliang93的博客
06-05 2098
一、PI的计算方法 程序中实现了4类14种PI的计算方法,每种方法都实测过,确保计算结果的准确性,所有方法至少试验过1~10万位的求解,输出有效数字完全相同,并与y-cruncher等标准程序输出结果进行了对照。 Method 1-7为类Machin公式,也就是反正切函数的Taylor级数;程序中实现了传统累加法和P2B3模型法(P2B3模型的含义在后面章节有专门介绍) Method 10-16为类BBP级数,包括标准BBP级数、Fabrice Bellard级数,程序实现了传统累加法和P2B3/BB
易语言精确计算&pi;
07-23
4. **Chudnovsky算法**:这是一种非常快速收敛的无穷级数,适用于高精度计算。 \( \frac{1}{\pi} = 12 \sum_{k=0}^{\infty} \frac{(-1)^k (6k)! (13591409 + 545140134k)}{(3k)!(k!)^3 (-640320)^{3k}} \) 源码中...
数据结构实验】NOJ002 实验1.2 高精度计算PI
weixin_45932570的博客
03-28 884
1. 题目 2. 分析 3. 代码 #include <iostream> #include <malloc.h> using namespace std; typedef struct node{ int data; struct node *pre; struct node *next; }Node; void createList(Node *head){ head->next = head; head->pre = head; Node *p
pi六轴算法_圆周率&pi;的计算历程及各种脑洞大开的估计方法
05-25
圆周率&pi;的计算历程可以追溯到公元前20世纪,当时古埃及人就已经开始研究圆周率的。随着时间的推移,人们不断尝试各种方法来计算&pi;的,包括使用几何方法、概率方法、级数方法和积分方法等。下面列举一些主要的计算&pi;的方法: 1. 几何方法:最早期的计算&pi;的方法就是几何方法,即通过将圆的周长与直径相除来计算&pi;的。这个方法的精度不高,但是很简单易行。 2. 概率方法:蒙特卡罗方法是一种概率方法,可以用来估计&pi;的。这个方法的原理是,将一个正方形内切一个圆,然后随机产生大量的点,统计落在圆内的点的数量,以此来估算&pi;的。 3. 级数方法:利用级数公式可以计算&pi;的,比如莱布尼兹级数、欧拉级数和马刁尔级数等。这些级数公式的精度较高,但是计算量较大。 4. 积分方法:用积分公式来计算&pi;的,比如阿贝尔-普朗克公式和矩形公式等。这些方法精度较高,但是计算量也比较大。 此外,还有一些脑洞大开的估计方法,比如: 1. 用切片面积估计&pi;的:将一个圆形的切片放在一个正方形内,然后统计切片内部的面积占正方形面积的比例,以此来估算&pi;的。 2. 用抛物线估计&pi;的:将一个抛物线放在一个正方形内,然后统计抛物线内部的面积占正方形面积的比例,以此来估算&pi;的。 3. 用牛顿迭代法估计&pi;的:利用牛顿迭代法可以求出&pi;的,但是迭代的次数较多,计算量很大。 总的来说,计算&pi;的方法有很多种,每种方法都有其优缺点和适用范围,选择何种方法取决于计算的精度要求和计算的时间限制。

后端领域新星创作者

75
原创
2460
点赞
2108
收藏
5778
粉丝
关注
私信
写文章

热门文章

  • 【算法】高精度计算π(pi)值 11656
  • 【数据结构】堆的全解析 11303
  • 【网络】HTTP协议详解 9203
  • 【刷题日记】动态规划经典题目 7080
  • 【刷题日记】贪心算法经典题目 4695

分类专栏

  • Redis 8篇
  • 蓝桥杯 5篇
  • 算法 12篇
  • Shell 1篇
  • 程序员必修 2篇
  • 项目 1篇
  • 设计模式 1篇
  • 数据结构 10篇
  • 杂谈 1篇
  • 网络 3篇
  • 刷题日记 15篇
  • C语言 20篇
  • C++ 1篇
  • 编程经典 1篇
  • 1篇

最新评论

  • 【Redis】Hash介绍与应用详解

    普通网友: 优质好文,支持支持。【我也写了一些相关领域的文章,希望能够得到博主的指导,共同进步!】

  • 【Redis】Hash介绍与应用详解

    普通网友: 感谢大佬分享好文,学到了不少新知识,支持大佬,期待大佬持续输出优质文章!【我也写了一些相关领域的文章,希望能够得到博主的指导,共同进步!】

  • 【Redis】List源码剖析

    栗筝i: 大佬的文章让我对这领域的技术问题有了更深入的了解,尤其是大佬提到的那些“坑点”,我相信能够在实际应用中避免或解决很多问题。谢谢大佬的分享,期待大佬的更多精彩文章,让我们共同学习、进步。

  • 【Redis】List源码剖析

    新梦空间: 博主文章很详细,感谢分享,期待博主持续带来更多优质好文。

  • 【Redis】ziplist与listpack源码剖析:Redis数据存储的演进与优化

    一代...: 优质好文支持支持

最新文章

  • 【Redis】Hash介绍与应用详解
  • 【Redis】List源码剖析
  • 【Redis】ziplist与listpack源码剖析:Redis数据存储的演进与优化
2024年15篇
2023年10篇
2022年27篇
2021年24篇

目录

目录

评论 71
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

白晨并不是很能熬夜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或 充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值

天下网标王爱美女性网站内优化方案网站推广优化王科杰11珲春市网站seo优化排名孝南区网站排名优化莞城电子网站优化服务宣城pc网站优化韶关资深的免费网站优化网站布局不利于优化武汉低价网站推广优化滨州网站seo优化案例珲春外贸网站优化河北网站优化厂家报价百灵鸟优化网站服务行业网站优化效果南通网站优化营商环境网站优化厂抖音优化网站建设这些淄川网站关键词优化网站优化视频教学网站展示优化包括什么公司网站排名优化手段优化网站的八大思考福州市网站优化公司策划内黄鹤壁网站优化三明市网站优化公司家政行业网站优化策划广州网站搜索引擎网站优化玉溪网站权重优化西安网站建设优化标准淄博网站优化价格一般是多少香港通过《维护国家安全条例》两大学生合买彩票中奖一人不认账让美丽中国“从细节出发”19岁小伙救下5人后溺亡 多方发声卫健委通报少年有偿捐血浆16次猝死汪小菲曝离婚始末何赛飞追着代拍打雅江山火三名扑火人员牺牲系谣言男子被猫抓伤后确诊“猫抓病”周杰伦一审败诉网易中国拥有亿元资产的家庭达13.3万户315晚会后胖东来又人满为患了高校汽车撞人致3死16伤 司机系学生张家界的山上“长”满了韩国人?张立群任西安交通大学校长手机成瘾是影响睡眠质量重要因素网友洛杉矶偶遇贾玲“重生之我在北大当嫡校长”单亲妈妈陷入热恋 14岁儿子报警倪萍分享减重40斤方法杨倩无缘巴黎奥运考生莫言也上北大硕士复试名单了许家印被限制高消费奥巴马现身唐宁街 黑色着装引猜测专访95后高颜值猪保姆男孩8年未见母亲被告知被遗忘七年后宇文玥被薅头发捞上岸郑州一火锅店爆改成麻辣烫店西双版纳热带植物园回应蜉蝣大爆发沉迷短剧的人就像掉进了杀猪盘当地回应沈阳致3死车祸车主疑毒驾开除党籍5年后 原水城县长再被查凯特王妃现身!外出购物视频曝光初中生遭15人围殴自卫刺伤3人判无罪事业单位女子向同事水杯投不明物质男子被流浪猫绊倒 投喂者赔24万外国人感慨凌晨的中国很安全路边卖淀粉肠阿姨主动出示声明书胖东来员工每周单休无小长假王树国卸任西安交大校长 师生送别小米汽车超级工厂正式揭幕黑马情侣提车了妈妈回应孩子在校撞护栏坠楼校方回应护栏损坏小学生课间坠楼房客欠租失踪 房东直发愁专家建议不必谈骨泥色变老人退休金被冒领16年 金额超20万西藏招商引资投资者子女可当地高考特朗普无法缴纳4.54亿美元罚金浙江一高校内汽车冲撞行人 多人受伤

天下网标王 XML地图 TXT地图 虚拟主机 SEO 网站制作 网站优化