如何找到以3.14159开头的首个π值?程序结果存疑求助
莱布尼茨公式估算π的精度判断问题
你遇到的情况其实是莱布尼茨级数的特性加上代码里的判断逻辑导致的——我帮你拆解清楚:
问题根源
莱布尼茨公式是交替级数,它的部分和会在真实π值(≈3.1415926535...)上下交替震荡收敛,也就是说,会出现“高于π→低于π→高于π→...”的循环,逐渐逼近真实值。
你的代码用了字符串截取的方式判断pi是否以3.14159开头,这里有两个坑:
to_string(pi)的转换会有精度误差:double类型的浮点数转字符串时,可能因为四舍五入导致数值接近3.14159时,字符串表现不符合预期。比如当pi实际是3.141589999999999,转换后可能变成3.1415900000;反过来3.1415900000000002也会被转成同样的字符串,但你用substr(0,7)严格匹配"3.14159",可能漏掉了一些实际符合条件的项。- 你的判断逻辑没考虑“高于π的情况”:比如某个项的部分和是
3.141593xxxx(比真实π大,但开头是3.14159),这其实符合你的要求,但可能因为字符串转换的问题没被检测到。
修复方案
把字符串判断改成数值范围判断更可靠——只要pi落在[3.14159, 3.14160)区间内,就说明它以3.14159开头。这样完全避开字符串转换的精度问题。
修改后的代码如下:
//piEstimation.cpp //估算数学常数π并确定何时得到以3.14159开头的数值 #include <iostream> #include <iomanip> using namespace std; int main(){ //初始化变量 double denominator{1.0}; double pi{0}; int terms; int firstDesiredTerm = -1; double desiredPi; //设置浮点数输出格式,保留小数点后10位 cout << setprecision(10) << fixed; const double lower_bound = 3.14159; const double upper_bound = 3.14160; for (terms = 1; ; terms++){ if(terms % 2 == 0){ //偶数项减去4/分母 pi -= 4.0 / denominator; } else{ //奇数项加上4/分母 pi += 4.0 / denominator; } //输出当前项数和估算值 cout << terms << "\t" << pi << endl; //判断是否落在目标区间内 if(pi >= lower_bound && pi < upper_bound){ firstDesiredTerm = terms; desiredPi = pi; break; } denominator += 2.0; } if(firstDesiredTerm != -1){ cout << "首次得到以3.14159开头的π值时,项数为" << firstDesiredTerm << ",对应的π值为" << desiredPi << endl; } else{ cout << "未找到符合条件的项数" << endl; } return 0; }
为什么这样修改?
- 数值范围判断直接针对你要的“开头是3.14159”的核心要求,不管
pi是比真实值大还是小,只要前五位小数是14159就会被检测到。 - 避免了字符串转换带来的精度歧义,double类型的精度足够处理这个区间的判断。
你可以运行这段修改后的代码,应该能找到更早的符合条件的项数——毕竟莱布尼茨级数在震荡过程中,会提前出现落在3.14159到3.14160之间的部分和。
内容的提问来源于stack exchange,提问作者Farshid
相关产品推荐
相关产品推荐

