如何计算pi(π)?

时间:2010-04-16 16:52:12

标签: algorithm math pi

如何编写一个将pi(π)返回到给定小数位数的函数?

速度不是问题。我一直在看http://bellard.org/pi/,但我仍然不明白如何获得pi的第n位数。

14 个答案:

答案 0 :(得分:29)

在微积分中有一个名为泰勒级数的东西,它提供了一种简单的方法来计算许多无理值到任意精度。

Pi / 4 = 1 - 1/3 + 1/5 - 1/7 + ...
(来自http://www.math.hmc.edu/funfacts/ffiles/30001.1-3.shtml

继续添加这些术语,直到您希望稳定的精确位数。

泰勒定理是一个强大的工具,但使用该定理推导出这一系列超出了问题的范围。如果您对更多细节感兴趣,那么它是标准的大学一年级微积分,并且很容易转换。


我并不是说暗示这是计算pi的最实用的方法。这取决于你真正需要这样做的原因。出于实际目的,您应该从许多已发布版本中的一个中复制所需数量的数字。我建议将其简单地介绍非理性值如何等同于无限级数。

答案 1 :(得分:26)

numeric approximation of π有许多算法。

答案 2 :(得分:11)

答案 3 :(得分:7)

作为JeffH存储每个变体的方法的替代方法,您只需存储最大位数并切断不需要的数字:

#include <string>
#include <iostream>
using std::cout; using std::endl; using std::string;

// The first 99 decimal digits taken from:
// http://www.geom.uiuc.edu/~huberty/math5337/groupe/digits.html
// Add more as needed.
const string pi =
  "1415926535"
  "8979323846"
  "2643383279"
  "5028841971"
  "6939937510"
  "5820974944"
  "5923078164"
  "0628620899"
  "8628034825"
  "342117067";

// A function in C++ that returns pi to X places
string CalcPi(const size_t decimalDigitsCount) 
{
  string returnValue = "3";
  if (decimalDigitsCount > 0)
  {
    returnValue += "." + pi.substr(0, decimalDigitsCount);
  }
  return returnValue;
} 

int main()
{
  // Loop through all the values of "pi at x digits" that we have. 
  for (size_t i = 0; i <= pi.size(); ++i) 
  {
    cout << "pi(" << i << "): " << CalcPi(i) << endl;
  } 
}

http://codepad.org/6mqDa1zj

答案 4 :(得分:5)

尝试“Computation of the n'th digit of pi in any base in O(n^2)”。它可能是最快的已知算法,不需要任意(读取巨大的)精度浮点数,并且可以直接在基数10(或任何其他)中提供结果。

答案 5 :(得分:5)

我相信您正在寻找的算法就是所谓的“Spigot算法”。一种特殊的是BBP(Bailey-Borwein-Plouffe)公式。

我相信这就是你要找的东西。

答案 6 :(得分:4)

π IN THE MANDELBROT SET”探讨了复杂平面上一系列点之间的奇妙关系以及如何计算它们的“Mandelbrot数”(因为缺少一个更好的术语......确定点数所需的迭代次数)在序列中不是Mandelbrot集的成员)与PI有关。

实践?可能不是。

出乎意料又有趣?我想是的。

答案 7 :(得分:2)

您可以根据您添加(或减去)的最后一个术语来判断精度。由于艾伦序列中每个项的幅度总是在减小,并且每个项在符号中交替出现,因此总和的变化不会超过上一个项。

翻译那个bab ::添加1/5后,总和的变化不会超过1/5,因此精确到1/5以内。当然,你必须将它乘以4,所以你真的只精确到4/5。

不幸的是,数学并不总是很容易转换为十进制数字。

答案 8 :(得分:2)

您是否愿意查找值而不是计算它们?

由于您没有明确指定您的函数必须计算值,如果您愿意为其计算的位数有一个上限,这里有一个可能的解决方案

// Initialize pis as far out as you want. 
// There are lots of places you can look up pi out to a specific # of digits.
double pis[] = {3.0, 3.1, 3.14, 3.141, 3.1416}; 

/* 
 * A function that returns pi out to a number of digits (up to a point)
 */
double CalcPi(int x)
{
    // NOTE: Should add range checking here. For now, do not access past end of pis[]
    return pis[x]; 
}

int main()
{
    // Loop through all the values of "pi at x digits" that we have.
    for (int ii=0; ii<(int)sizeof(pis)/sizeof(double); ii++)
    {
        double piAtXdigits = CalcPi(ii);
    }
}

以这种方式编写CalcPi()(如果它符合您的需要)有一个附带好处,就是在上限内对任何X值快速同等地尖叫。

答案 9 :(得分:2)

我从公式

开始
pi = 16 arctan (1/5) - 4 arctan (1/239)

谷歌很容易找到正常人可以理解的这个公式的证明,以及计算反正切函数的公式。这将允许您非常容易和快速地计算pi的几千个十进制数字。

答案 10 :(得分:2)

我的2美分...这可能不是最快的,但我认为这很容易理解。我在一次数学讲座中自己想到了它,而在文学中没有真正见过它。我要么是个天才,要么很愚蠢,要么不真正关注阅读有关数学的书籍,或者是以上所有...:)

无论如何...从单位圆开始。我们知道x ^ 2 + y ^ 2 = 1,所以y = sqrt(1-x ^ 2)。我们也知道单位圆的面积是PI。如果现在将函数sqrt(1-x ^ 2)的整数取为0到1,我们将得到四分之一的PI。因此,将其乘以4得到PI:

PI formula

如果我们尝试分析地解决这一问题,我相信我们只会收回PI。但是编写程序以数字方式求解它很容易。 C中有以下内容:

#include <math.h>
#include <stdio.h>

void main(void) {
    double interval=0.0000001,area=0,x,y;

    for (x=0; x<1; x+=interval)
        area+=4*interval*sqrt(1-x*x);

    printf("pi ~ %.20f\n",area);
}

使用上述interval的设置运行它,我们得到:

pi ~ 3.14159285415672595576

因此10,000,000次迭代给出6个正确的小数。不是最有效的,但这是我的宝贝...:)

答案 11 :(得分:0)

pi = function () {
    let pi = 3;
    let a = 3;
    let even = false;
    let turn;

    while (a <= 90000) {
        turn = (4/((Math.pow(a, 3)) - (a)));

        if(even){
            turn = turn*-1;
            even = false;
        } else {
            even = true;
        }
        pi = pi + turn;
        a = a + 2;
    }
    return pi;
};

答案 12 :(得分:0)

import math
def pi(x):
    for i in range(1,x):
        print( (360.0*math.tan(math.radians(1/(2*i))))/(1/i))

这就像获得尽可能小的结果,然后我使用该角度来计算否。的侧面。

边的长度是使用三角函数计算的,然后...您也可以将math.tan替换为math.sin

答案 13 :(得分:-4)

考虑这是一个粗略的草图,但这是一个初学者可以实现的直接方法。

int x = 9;
double pi = double(22/7);
String piAsString = pi.toString();
String valueAtXPosition = piAsString.subString(x, x+1);
int valueAtXPosAsInt = Integer.parseInt(valueAtXPosition);
相关问题