当前位置: 首页 > news >正文

尝试用程序计算Π(3.141592653......)

文章目录

1. π\piπ

π\piπ的重要性或者地位不用多说,有时候还是很好奇,精确地π\piπ值是怎么计算出来的。研究π\piπ的精确计算应该是很多数学家计算机科学家努力的方向,很多算式看起来和π\piπ没有一点关系,但是最后的表达式中却包含π\piπ
作为一个国家定义的从事信息技术的“新时代农民工”,要验证某些式子相对来说就容易得多了。

2. 用微积分来计算π\piπ

2.1 原理

小学时候就知道了圆的面积公式S=πr2S=\pi r^2S=πr2,到了高中学习了微积分,方程与曲线之后可以知道:
x2+y2=r2x^2 + y^2 = r^2x2+y2=r2
表示一个圆,如果y>=0y>=0y>=0则表示上半圆,这个时候上半圆可以表达为一个函数:
y=(r2−x2)y = \sqrt{(r^2-x^2)}y=(r2x2)
当它是一个单位圆时(r=1)图形如下所示:
r=1
根据从微积分的角度来看曲线y(x)与x=0,x∈[−r,r]y(x)与x=0,x\in [-r,r]y(x)x=0x[r,r]围成的区域面积,就是圆面积的一半,即上半圆的面积。令圆面积为S,则有:令圆面积为S,则有:令圆面积为S,则有:
S=πr2=2∫−rr(r2−x2)dxS = \pi r^2 = 2\int_{-r}^{r} \sqrt{(r^2-x^2)} dxS=πr2=2rr(r2x2)dx
现在的工作就变成计算上面右侧的积分式了。积分式用化曲为直(马师傅称为:接 化 发),把圆分成许多直立的小矩形,再求和,小矩形的高为yi=(r2−xi2),宽为Δx,Δx=1ny_i=\sqrt{(r^2-x_{i}^2)},宽为\Delta x, \Delta x=\frac{1}{n}yi=(r2xi2),宽为Δx,Δx=n1,n表示把圆的面积分为n个小矩形的面积来近似,n越大则近似程度越好,而且当n趋近于无穷时就和积分式完全一致了。
为了求π\piπ那我们只需要用程序帮我们把圆分成一个一个的小矩形再求和就行了,设定圆的半径,每个矩形的宽度,就可以计算积分式的近似值了。

下面的程序就来计算下式
π=2r2∫−rr(r2−x2)dx\pi = \frac{2}{r^2}\int_{-r}^{r} \sqrt{(r^2-x^2)} dxπ=r22rr(r2x2)dx

2.2 代码

#include <cmath>
#include <iostream>/*** @brief calculate sqrt(r^2-x^2)* * @param x  : * @return constexpr long double */
constexpr inline long double IntegralFormula(const long double radius,const long double x)
{return std::sqrt(radius*radius-x*x);
} /*** @brief 计算曲线y=sqrt(r^2-x^2),在 x in [-r,r]的积分* * @param radius  : * @param delta_x  : * @return constexpr long double */
constexpr long double Integral(const long double radius,const long double delta_x)
{long double sum = 0.0;for (double x = -radius; x <= radius; x += delta_x){sum += delta_x * IntegralFormula(radius,x);}return sum;
}/*** @brief * * @param radius  : 半径* @param bin_num  : 分成小矩形的数目* @return constexpr long double */
constexpr long double CalculatePi(const long double radius,double bin_num)
{long double delta_x = 2 * radius / bin_num;long double integral = Integral(radius,delta_x);long double pi = integral * 2.0 / (radius * radius);return pi;
}/*** @brief 计算pi值,用单位圆的上半圆做积分,y=sqrt(r^2-x^2),x in [-r,r]* */
void Test()
{constexpr long double true_pi = 3.141592653589793;printf("True PI: %.15Lf\n",true_pi);for(double radius = 10; radius <= 100; radius*=10)for(double bin_num = 100000; bin_num <= 10000000; bin_num*=10){printf("radius:%f, \t bin_num: %f,\t pi: %.20Lf \n",radius,bin_num,CalculatePi(radius,bin_num));}}void Test2()
{double radius = 10000;double bin_num = 100000;printf("radius:%f, \t bin_num: %f,\t pi: %.20Lf \n",radius,bin_num,CalculatePi(radius,bin_num));
}int main()
{Test();Test2();return 0;
}

2.3 结果

输出

True PI: 3.141592653589793
radius:10.000000,        bin_num: 100000.000000,         pi: 3.14159254840509465393
radius:10.000000,        bin_num: 1000000.000000,        pi: 3.14159265028029712060 
radius:10.000000,        bin_num: 10000000.000000,       pi: 3.14159265331958147799 
radius:100.000000,       bin_num: 100000.000000,         pi: 3.14159254846500206543
radius:100.000000,       bin_num: 1000000.000000,        pi: 3.14159265024260935645 
radius:100.000000,       bin_num: 10000000.000000,       pi: 3.14159265331696711159 
radius:10000.000000,     bin_num: 100000.000000,         pi: 3.14159254840753097960

2.4 分析

这重方式用long double的计算精度,但是最后计算的精度最高只到"3.141592653",小数点后9位。分再多的小矩形也没用了,因为计算时候的截断误差已经足够影响计算精度了。不知道有没有什么好的策略保持计算精度的。

http://www.lryc.cn/news/21304.html

相关文章:

  • 【异常检测三件套】系列3--时序异常检测综述
  • 关于SAP 错误日志解析
  • java:自定义变量加载到系统变量后替换shell模版并执行shell
  • Redis高级删除策略与数据淘汰
  • 社畜大学生的Python之pandas学习笔记,保姆入门级教学
  • 20_FreeRTOS低功耗模式
  • Hive的使用方式
  • Flume三大核心组件
  • 数据结构(六)二叉树
  • Docker buildx 的跨平台编译
  • 【java基础】方法重载和方法重写
  • Gradle7.4安装与基本使用
  • [系统安全] 虚拟化安全之虚拟化概述
  • 如何从零开始系统的学习项目管理?
  • 面试题-----
  • 线材-电子线载流能力
  • 单变量回归问题
  • ubuntu/linux系统知识(36)linux网卡命名规则
  • java的一些冷知识
  • java代理模式
  • JUC包:CountDownLatch源码+实例讲解
  • Log4j2基本使用
  • A2L在CAN FD总线的使用
  • Android JetPack之启动优化StartUp初始化组件的详解和使用
  • [11]云计算|简答题|案例分析|云交付|云部署|负载均衡器|时间戳
  • C++11/C++14:lambda表达式
  • 算法课堂-分治算法
  • 操作系统权限提升(十六)之绕过UAC提权-CVE-2019-1388 UAC提权
  • 实例9:四足机器人运动学正解平面RR单腿可视化
  • 堆的基本存储