You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Viete嵌套平方根公式计算PI时结果异常的问题排查

问题:用Viete嵌套平方根公式近似π的C++代码错误排查

我尝试用Viete的2的嵌套平方根公式近似计算圆周率π,编写了如下C++代码:

#include <iostream>
#include <iomanip>
#include <cmath>

using namespace std;
int main()
{
    int k; //variable for user input
    int n = 1; //built integer that causes the program to loop
    double result;
    //greeting message, start of program
    cout << "Welcome to the Approx PI program.\n";
    cout << "Please enter in a value for k...\n";
    cin >> k;
    //if user inputs a number outside the interval
    while (k < 1 || k > 30)
    {
        cout << "Invalid ---k must be >=1 and <=30\n";
        cout << "Please enter in a value for k...\n";
        cin >> k;
    }
    //calculating PI with the nested square root formula
    while (n <= k - 1)
    {
        result = sqrt(2 + result);
        n++;
    }
    result = pow(2, k) * sqrt(2 - result);
    //outputs the result, end of program
    cout << "Approx PI =         " <<setprecision(20)<<fixed<<result<<endl;
    return 0;
}

但输入k=28时,程序输出结果为4;输入k=29或30时,结果为0。我预期k=30时应得到结果:3.14245127249413367895,请问我的代码哪里出错了?


解答

你的代码存在两个关键问题,其中未初始化变量是导致异常输出的核心原因:

  1. result变量未初始化
    你声明了double result;但没有赋初始值,这会导致它的初始值是内存中的随机垃圾值。Viete公式的迭代起点必须是0.0,因为第一层嵌套根号的计算是sqrt(2 + 0),后续迭代需要基于这个正确起点展开。
    未初始化的垃圾值会让迭代过程完全偏离正确路径,当k增大时,迭代结果会逐渐收敛到2(因为sqrt(2+2)=2,进入不动点循环),此时sqrt(2 - result)会趋近于0,最终导致pow(2,k)*0输出0;k=28时的异常输出4,是垃圾值迭代过程中偶然出现的中间错误结果。

  2. 可选优化:pow(2,k)的精度问题
    虽然不是当前错误的直接原因,但用pow计算2的整数次幂会引入微小精度误差。对于k<=30的场景,用static_cast<double>(1LL << k)代替pow(2,k)精度更高——因为2^30在double的精确表示范围内,移位运算的结果完全准确。


修正后的代码
#include <iostream>
#include <iomanip>
#include <cmath>

using namespace std;
int main()
{
    int k;
    int n = 1;
    double result = 0.0; // 初始化迭代起点为0.0
    cout << "Welcome to the Approx PI program.\n";
    cout << "Please enter in a value for k...\n";
    cin >> k;
    
    while (k < 1 || k > 30)
    {
        cout << "Invalid ---k must be >=1 and <=30\n";
        cout << "Please enter in a value for k...\n";
        cin >> k;
    }
    
    while (n <= k - 1)
    {
        result = sqrt(2 + result);
        n++;
    }
    // 用移位运算替代pow,提升精度
    result = static_cast<double>(1LL << k) * sqrt(2 - result);
    
    cout << "Approx PI =         " << setprecision(20) << fixed << result << endl;
    return 0;
}

修正后输入k=30,会得到你预期的近似值:3.14245127249413367895。


内容的提问来源于stack exchange,提问作者Aacro

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 02:20:36