使用Bellard公式近似计算π时始终得到3.145063的问题求助
Bellard公式计算π结果异常的问题修复
问题根源
- 整数除法错误:代码中
1/(4*n+3)这类表达式,分子分母均为整数类型,会触发整数除法(直接截断小数部分),导致每一项的计算结果严重偏离公式要求。 - Bellard公式系数错误:原公式中第一项应为
-1/(4n+1),但代码里错误地写成了-(pow(2,5))/(4n+1),多乘了2^5,这是结果始终固定的核心原因。 pow(-1, n)的精度隐患:使用pow计算正负交替值,当n较大时可能出现精度误差,不如直接通过判断n的奇偶性生成符号更可靠。- 输出精度不足:
std::to_string默认只保留6位小数,无法展示更多有效位数,且会自动截断或四舍五入。
修复后的代码
#include <iostream> #include <cmath> #include <iomanip> double approximate(int iterations) { double summed = 0.0; for (int n = 0; n < iterations; ++n) { // 用奇偶性判断符号,替代pow(-1, n) double sign = (n % 2 == 0) ? 1.0 : -1.0; double denom_2_10n = pow(2, 10 * n); double term = sign / denom_2_10n; // 修正公式系数,所有常量转为浮点型避免整数除法 double part1 = -1.0 / (4.0 * n + 1.0); double part2 = -1.0 / (4.0 * n + 3.0); double part3 = pow(2, 8) / (10.0 * n + 1.0); double part4 = -pow(2, 6) / (10.0 * n + 3.0); double part5 = -pow(2, 2) / (10.0 * n + 5.0); double part6 = -pow(2, 2) / (10.0 * n + 7.0); double part7 = 1.0 / (10.0 * n + 9.0); summed += term * (part1 + part2 + part3 + part4 + part5 + part6 + part7); } // 公式中的1/2^6转为浮点型计算 return summed / pow(2, 6); } int main() { std::cout << "How many iterations?: "; int iterations; std::cin >> iterations; double approx = approximate(iterations); // 设置输出精度为15位小数,展示更多有效位数 std::cout << std::fixed << std::setprecision(15) << approx << std::endl; return 0; }
修复说明
- 把所有除法运算的分子或分母转为
double类型(比如1.0代替1),确保执行浮点除法而非整数除法。 - 修正了Bellard公式的核心系数错误,移除了第一项多余的
2^5因子。 - 用奇偶判断生成正负符号,避免
pow(-1, n)的精度问题。 - 使用
std::fixed和std::setprecision设置输出精度,能看到更多计算结果的有效位数,同时替换了std::to_string的低精度输出方式。 - 调整了变量名(
digits改为iterations),因为输入的是迭代次数而非想要计算的位数,避免概念混淆。
内容的提问来源于stack exchange,提问作者Jake StBu
相关产品推荐
相关产品推荐

