计算莱布尼茨求和的迭代次数,用于π C++



我的任务是询问用户,与 pi 的实际值相比,他们希望总和迭代多少位小数位精度。因此,当循环达到 3.14 时,小数点后 2 位将停止。我有一个完整的程序,但我不确定它是否真的按预期工作。我已经用计算器检查了 0 和 1 小数位,它们似乎有效,但我不想假设它适用于所有人。此外,我的代码可能有点笨拙,因为仍在学习基础知识。我们刚刚学习了循环和嵌套循环。如果有任何明显的错误或可以清理的部分,我将不胜感激任何意见。编辑:我只需要让这项工作最多小数点后五位。这就是为什么我的圆周率值不精确。很抱歉误会。

#include <iostream>
#include <cmath>
using namespace std;
int main() {
const double PI = 3.141592;
int n, sign = 1;
double sum = 0,test,m;
cout << "This program determines how many iterations of the infinite series   forn"
        "pi is needed to get with 'n' decimal places of the true value of pi.n"
        "How many decimal places of accuracy should there be?" << endl;
cin >> n;
double p = PI * pow(10.0, n);
p = static_cast<double>(static_cast<int>(p) / pow(10, n));
int counter = 0;
bool stop = false;
for (double i = 1;!stop;i = i+2) {
    sum = sum + (1.0/ i) * sign;
    sign = -sign;
    counter++;
    test = (4 * sum) * pow(10.0,n);
    test = static_cast<double>(static_cast<int>(test) / pow(10, n));
        if (test == p)
            stop = true;
}
cout << "The series was iterated " << counter<< " times and reached the value of pinwithin "<< n << " decimal places." << endl;
return 0;
}

莱布尼茨求和的问题之一是它具有极低的收敛率,因为它表现出亚线性收敛。在您的程序中,您还可以将计算出的π消光与给定值(6 位近似值)进行比较,而求和的重点应该是找出正确的数字。

如果所需的数字在迭代之间没有变化,您可以稍微修改代码以使其终止计算(我还添加了最大迭代次数检查)。请记住,您使用的是double不是无限的精度数字,舍入误差迟早会影响计算。事实上,此代码的真正限制是它所需的迭代次数(获得3.141592653 的迭代次数为 2,428,700,925)。

#include <iostream>
#include <cmath>
#include <iomanip>
using std::cout;
// this will take a long long time...
const unsigned long long int MAX_ITER = 100000000000;
int main() {
    int n;
    cout << "This program determines how many iterations of the infinite series forn"
            "pi is needed to get with 'n' decimal places of the true value of pi.n"
            "How many decimal places of accuracy should there be?n";
    std::cin >> n;
    // precalculate some values
    double factor = pow(10.0,n);
    double inv_factor = 1.0 / factor;
    double quad_factor = 4.0 * factor;
    long long int test = 0, old_test = 0, sign = 1;
    unsigned long long int count = 0;
    double sum = 0;
    for ( long long int i = 1; count < MAX_ITER; i += 2 ) {
        sum += 1.0 / (i * sign);
        sign = -sign;
        old_test = test;
        test = static_cast<long long int>(sum * quad_factor);
        ++count;
        // perform the test on integer values
        if ( test == old_test ) {
            cout << "Reached the value of Pi within "<< n << " decimal places.n";
            break;          
        }
    } 
    double pi_leibniz = static_cast<double>(inv_factor * test);
    cout << "Pi = " << std::setprecision(n+1) << pi_leibniz << 'n';    
    cout << "The series was iterated " << count << " timesn";
    return 0;
}

我在此表中总结了几次运行的结果:

digits        Pi           iterations
---------------------------------------
 0        3                           8
 1        3.1                        26
 2        3.14                      628
 3        3.141                   2,455
 4        3.1415                136,121
 5        3.14159               376,848
 6        3.141592            2,886,751
 7        3.1415926          21,547,007
 8        3.14159265        278,609,764
 9        3.141592653     2,428,700,925
10        3.1415926535   87,312,058,383

你的程序永远不会终止,因为test==p永远不会是真的。这是计算方式不同的两个双精度数字之间的比较。由于舍入误差,即使您运行无限次迭代,它们也不会相同,并且您的数学是正确的(现在不是,因为程序中PI的值不准确)。

为了帮助您弄清楚发生了什么,请在每次迭代中打印 test 的值,以及 testpi 之间的距离,如下所示:

#include<iostream>
using namespace std;
void main() {
    double pi = atan(1.0) * 4; // Make sure you have a precise value of PI
    double sign = 1.0, sum = 0.0;
    for (int i = 1; i < 1000; i += 2) {
        sum = sum + (1.0 / i) * sign;
        sign = -sign;
        double test = 4 * sum;
        cout << test << " " << fabs(test - pi) << "n";
    }
}

确保程序运行良好后,最终将停止条件更改为基于 testpi 之间的距离。

for (int i=1; fabs(test-pi)>epsilon; i+=2)

最新更新