Как рассчитывается число пи (π)?

Как я могу написать функцию, которая будет возвращать число пи (π) с заданным числом знаков после запятой?

Скорость не беспокоит. Я просматривал http://bellard.org/pi/, но так и не понял как получить энную цифру числа пи.


person jmasterx    schedule 16.04.2010    source источник
comment
en.wikipedia.org/wiki/Pi — хорошая отправная точка.   -  person Bill    schedule 16.04.2010
comment
Кроме того, вам нужно вычислить Пи или просто отформатировать Пи?   -  person Bill    schedule 16.04.2010
comment
вы можете посмотреть запись вычислений Pi bellard.org/pi/pi2700e9 просто для удовольствия..   -  person LB40    schedule 16.04.2010
comment
В сходящемся ряду с чередованием положительных и отрицательных членов ряд будет чередоваться выше и ниже целевого значения. Итак, вы знаете из этого, что значение всегда будет между термином n и термином n+1. Если термин n и термин n+1 совпадают по первым k цифрам, то вы знаете, что ваше целевое значение составляет k цифр. Короче говоря, вы получаете k цифр точности, останавливаясь, когда первые k цифр перестают изменяться. (Непеременные ряды работают иначе.)   -  person Alan    schedule 17.04.2010
comment
Другие примеры этого типа здесь: en.wikipedia.org/wiki/Convergent_series   -  person Alan    schedule 17.04.2010
comment
Хорошо, вы хотите иметь возможность вычислять число пи, используя обычную компьютерную арифметику, или вы хотите вычислять число пи с большей точностью, чем это обычно доступно (IEEE 64-битное число с плавающей запятой)?   -  person David Thornley    schedule 12.08.2010


Ответы (10)


В исчислении есть вещь, называемая рядами Тейлора, которая обеспечивает простой способ вычисления многих иррациональных значений с произвольной точностью.

Пи/4 = 1 - 1/3 + 1/5 - 1/7 + ...
(из http://www.math.hmc.edu/funfacts/ffiles/30001.1-3).shtml )

Продолжайте добавлять эти термины до тех пор, пока не стабилизируется требуемое количество цифр точности.

Теорема Тейлора — мощный инструмент, но вывод этого ряда с помощью теоремы выходит за рамки вопроса. Это стандартное исчисление для первокурсников университета, и его легко найти в Google, если вас интересуют подробности.


Я не имел в виду, что это самый практичный метод вычисления числа пи. Это будет зависеть от того, почему вам действительно нужно это сделать. Для практических целей вы должны просто скопировать столько цифр, сколько вам нужно, из одной из многих опубликованных версий. Я предлагал это как простое введение в то, как иррациональные ценности могут быть приравнены к бесконечным рядам.

person Alan    schedule 16.04.2010
comment
Что происходит, когда я хочу превысить лимит int64 (double)? - person jmasterx; 16.04.2010
comment
Кроме того, как я могу определить, с какой точностью я получаю, например: 1 десятичный знак на 500 итераций.... - person jmasterx; 16.04.2010
comment
Эта серия Тейлора, вероятно, является одним из худших способов создания PI на компьютере. Вы должны иметь огромную точность в своих вычислениях, и потребуются многие миллиарды итераций, чтобы пройти 3,14159. Давай, попробуй и увидишь. Или вот сайт, где об этом говорится: cygnus-software.com/misc/pidigits. htm - person indiv; 16.04.2010
comment
Я помню, как писал это на C++ и QuickBasic и обнаружил, что версия QuickBasic на самом деле генерирует PI быстрее:/ - person NibblyPig; 16.04.2010
comment
на x86 (на самом деле x87) используйте тип long double. Это 10-байтовое число. Вы также можете использовать класс, подобный BigDecimal. Интересно, что в x86 есть инструкции fldpi, которые загружают pi в fpu, а fstp tword MEM_LOC можно использовать для сохранения в 10-байтовой ячейке памяти. - person KitsuneYMG; 16.04.2010
comment
@kts: Это все еще не меняет того факта, что вам нужны миллиарды итераций для любого достаточно точного ответа. - person Billy ONeal; 16.04.2010
comment
@ user146780: Просто. Обратите внимание, что члены последовательно уменьшаются и поочередно добавляются и вычитаются. Поэтому, когда вы добавляете термин, вы определенно выше реального π. Когда вы вычитаете, вы, безусловно, ниже. Таким образом, последние две частичные суммы обеспечивают верхнюю и нижнюю границы истинного значения. - person slacker; 16.04.2010
comment
@indiv: безусловно, есть много рядов, которые сходятся быстрее. Но этот простой и может быть более подходящим для праздного упражнения по программированию, которое, как я полагал, было целью вопроса. @ user146780: если я неправильно истолковал ваш смысл, и вы собираетесь использовать это в производственном коде. Не делайте этого. Возьмите столько цифр, сколько вам нужно, из опубликованной версии в сети и сохраните ее. - person Alan; 16.04.2010
comment
@Alan: Хорошо, но в вопросе ясно сказано, что он пытается написать функцию, которая может вычислять PI в X местах ... В любом случае, я реализовал эту серию Тейлора, и после 1 миллиарда итераций у вас есть 3,14159265. После 3 миллиардов итераций у вас есть следующая цифра. Цифра после этого появляется после 99 миллиардов итераций. 99 миллиардов. - person indiv; 17.04.2010
comment
Да, если вам нужны n десятичных цифр точности, вам понадобится что-то порядка 10 ^ n итераций. Я не спорю, что он сходится медленно. ОП, кажется, интересуется учебным упражнением, а не чем-то практически полезным. - person Alan; 17.04.2010
comment
Для этого требуется BigNum и O(n) пробел, чтобы найти n-е место. Существуют O(1) пространственные алгоритмы для n-го двоичного разряда числа π, но я не уверен, что такой алгоритм существует для n-го десятичного разряда. - person R.. GitHub STOP HELPING ICE; 08.02.2011
comment
Погуглите, если вам нужен ответ, который я получил и теперь я здесь. - person ryvantage; 05.02.2020

В качестве альтернативы методу 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

person Bill    schedule 16.04.2010
comment
Учитывая, что число «пи» не изменится и что 43 цифры — достаточная точность для вычисления длины окружности Вселенной с точностью до ширины 1 протона, это вполне разумно. К сожалению, вопрос касается вычисления X-й цифры и не обязательно означает, что вам нужно получить цифры до цифры X, и это не будет решением здесь, поскольку X может быть чем угодно! - person Neil Trodden; 18.04.2010


Я полагаю, что алгоритм, который вы ищете, известен как "алгоритм патрубка". Одним из конкретных видов является формула BBP (Bailey-Borwein-Plouffe).

Я считаю, что это то, что вы ищете.

person Mike Bailey    schedule 20.04.2010

"π В МНОЖЕСТВЕ МАНДЕЛЬБРОТА" исследует любопытную взаимосвязь между последовательностью точек на комплексной плоскости и тем, как вычисляется их "число Мандельброта" (за неимением лучшего термина... количество итераций, необходимых для определения того, что точки в последовательности не являются членами множество Мандельброта) относится к ПИ.

Практичный? Возможно нет.

Неожиданно и интересно? Я так думаю.

person andand    schedule 16.04.2010

Я бы начал с формулы

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

Google легко найдет доказательство этой формулы, понятное обычным людям, и формулу для вычисления функции арктангенса. Это позволит вам легко и быстро вычислить несколько тысяч десятичных знаков числа пи.

person gnasher729    schedule 27.08.2014

Готовы ли вы искать значения вместо их вычисления?

Поскольку вы явно не указали, что ваша функция должна вычислять значения, вот возможное решение, если вы хотите иметь верхний предел количества цифр, которые она может "вычислить":

// 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 в пределах вашего верхнего предела.

person JeffH    schedule 16.04.2010
comment
Это решение может быть связано с вычислительным решением: массив может быть объявлен в файле .hpp и определен (то есть заполнен) метапрограммой, создающей соответствующий файл .cpp. Метапрограмма будет параметризована максимальным количеством необходимых цифр и будет вычислять значения, чтобы установить их в массив. - person Luc Touraille; 17.04.2010

Мои пять копеек... Это может быть не самым быстрым, но я думаю, что это довольно легко понять. Я придумал это сам во время лекции по математике и больше нигде в литературе не встречал. Либо я гений, совсем тупой, либо не особо обращаю внимание на чтение книг по математике, либо все вышеперечисленное... :)

В любом случае... Начните с единичного круга. Мы знаем, что x^2+y^2=1, поэтому y=sqrt(1-x^2). Мы также знаем, что площадь единичного круга равна PI. Если мы теперь возьмем интеграл функции sqrt(1-x^2) в диапазоне от 0 до 1, мы получим четверть PI. Умножьте это на 4, чтобы получить PI:

формула PI

Если бы мы попытались решить это аналитически, я уверен, мы бы просто вернули 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 правильных знаков после запятой. Не самый эффективный, но это мое детище... :)

person Mikael Lindqvist    schedule 28.11.2018
comment
Это основано на предположении, что числа с плавающей запятой ведут себя как рациональные числа. Это предположение неверно. В зависимости от входных данных эта реализация дает сильно разные результаты. Точность результата остается неизвестной. - person IInspectable; 21.12.2019

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.

person xavier    schedule 30.07.2020

person    schedule
comment
@t-arnold, вы реализовали функцию, но было бы неплохо также получить какое-то объяснение. - person Sergii; 23.11.2017