有趣的PI运算

! 没写完,先别看T.T

在人类发展的历史长河上,PI是美妙的,同时也是人类认知圆这一图形的钥匙。既然PI是一个无理数,那么自然我们需要用一定的算法才可以进行迭代解算,本文将对几个经典算法进行实现。

1. 计算公式

自从1593年伟大的数学家韦达发现了使用无穷乘积来计算π后,全世界各地的神人们都研究并发表了很多的计算方法,以下是常见的几种:
有趣的PI运算_第1张图片
(图片引用自:http://tieba.baidu.com/p/1392156294)

外加一个Newton-Leibniz: pi = 3 + 4/(2*3*4) - 4/(4*5*6) + 4/(6*7*8) - 4/(8*9*10) …(实测这个方法很好用啊 _(:з」∠)_ )

上述算法实现起来非常简单,但是,π的计算重在一个精确,动辄就是好几百位几千位的小数,在不考虑我们可爱的大数乘除法的前提下,这明显不讲理嘛,我们不禁思考:计算机能够表示这么长的数吗?

于是乎,我开始查阅论文。。。
查阅中,请稍后。。。




图书馆网速好慢
有趣的PI运算_第2张图片


额,我们还是先把代码实现出来吧。

2. 系统架构

1) class: Algorithm

就是放置各种算法的一个类

#include 
#include 

class Algorithm
{
public:
    Algorithm();

    long double Vieta(long int iterationNum);
    long double Leibniz(long int iterationNum);
    long double Newton(long int iterationNum);
    long double Newton_Leibniz(long int iterationNum);
    long double Sharp(long int iterationNum);
    long double Euler(long int iterationNum);

private:
    long long int fact(int f);
};
  • 为了让输出尽可能的高,用了最大的long double来定义函数返回值。
  • iterationNum 是迭代次数,为了适应未来可能的超大迭代次数,这里用了long型(虽然在前期这看起来又傻效率又低)

接下来就是具体实现:

long double Algorithm::Vieta(long int iterationNum)
{
    long double pi = sqrt(0.5);
    for(int i=0;isqrt(0.5 + 0.5 * pi_2);
    }
    return 2/pi;
}

long double Algorithm::Leibniz(long int iterationNum)
{
    long double pi = 0;
    long double d  = 1.0;
    for(int i=0;i1.0/d) * pow(-1,i);
        d  += 2.0;
    }
    return 4*pi;
}

long double Algorithm::Newton(long int iterationNum)
{
    long double pi = 0;
    for(int i=0;i1.0 / (pow(4,i) * fact(1+2*i));
    }
    return 3*pi;
}

long double Algorithm::Newton_Leibniz(long int iterationNum)
{
    long double pi = 3.0;
    long long int j;
    for(int i=1;i2*i;
        pi += (4.0 / (j*(j+1)*(j+2))) * pow(-1,i-1);
    }
    return pi;
}

long double Algorithm::Sharp(long int iterationNum)
{
    long double pi = 0;
    for(int i=0;i1.0 / ((1+2*i) * pow(3,i))) * pow(-1,i);
    }
    pi *= sqrt(1.0/3);
    return 6*pi;
}

long double Algorithm::Euler(long int iterationNum)
{
    long double pi = 0;
    for(int i=1;i1.0/(i*i);
    }
    return sqrt(pi*6);
}

long long int Algorithm::fact(int f)
{
    if(f <= 1){
        return 1;
    }
    long long int r = 1;
    for(int i=1;i<=f;i++){
        r *= i;
    }
    return r;
}

这里需要说明一下,在Newton_Leibniz()这个函数中,我使用了一个临时变量j来存储临时乘法结果,而不是直接使用i来构造连续乘法。这是因为c会将乘法结果放置在当前参数类型下的一个临时变量中,也就是说,int * int = int,然而int的上界很小,当i稍大一些时,我们的函数就会有溢出的问题,因此使用了一个long long 型的变量来解决这个问题。

突然想到能否使用static_cast进行显式转型解决,试试看。。。

然而并不好用

该系列在ANC课程结束的那一瞬间进入墓地,等待重启。。。

你可能感兴趣的:(C++)