Как я могу написать функцию, которая будет возвращать число пи (π) с заданным числом знаков после запятой?
Скорость не беспокоит. Я просматривал http://bellard.org/pi/, но так и не понял как получить энную цифру числа пи.
Как я могу написать функцию, которая будет возвращать число пи (π) с заданным числом знаков после запятой?
Скорость не беспокоит. Я просматривал http://bellard.org/pi/, но так и не понял как получить энную цифру числа пи.
В исчислении есть вещь, называемая рядами Тейлора, которая обеспечивает простой способ вычисления многих иррациональных значений с произвольной точностью.
Пи/4 = 1 - 1/3 + 1/5 - 1/7 + ...
(из http://www.math.hmc.edu/funfacts/ffiles/30001.1-3).shtml )
Продолжайте добавлять эти термины до тех пор, пока не стабилизируется требуемое количество цифр точности.
Теорема Тейлора — мощный инструмент, но вывод этого ряда с помощью теоремы выходит за рамки вопроса. Это стандартное исчисление для первокурсников университета, и его легко найти в Google, если вас интересуют подробности.
Я не имел в виду, что это самый практичный метод вычисления числа пи. Это будет зависеть от того, почему вам действительно нужно это сделать. Для практических целей вы должны просто скопировать столько цифр, сколько вам нужно, из одной из многих опубликованных версий. Я предлагал это как простое введение в то, как иррациональные ценности могут быть приравнены к бесконечным рядам.
fldpi
, которые загружают pi в fpu, а fstp tword MEM_LOC
можно использовать для сохранения в 10-байтовой ячейке памяти.
- person KitsuneYMG; 16.04.2010
O(n)
пробел, чтобы найти n-е место. Существуют O(1)
пространственные алгоритмы для n-го двоичного разряда числа π, но я не уверен, что такой алгоритм существует для n-го десятичного разряда.
- person R.. GitHub STOP HELPING ICE; 08.02.2011
В качестве альтернативы методу 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;
}
}
Я полагаю, что алгоритм, который вы ищете, известен как "алгоритм патрубка". Одним из конкретных видов является формула BBP (Bailey-Borwein-Plouffe).
Я считаю, что это то, что вы ищете.
"π В МНОЖЕСТВЕ МАНДЕЛЬБРОТА" исследует любопытную взаимосвязь между последовательностью точек на комплексной плоскости и тем, как вычисляется их "число Мандельброта" (за неимением лучшего термина... количество итераций, необходимых для определения того, что точки в последовательности не являются членами множество Мандельброта) относится к ПИ.
Практичный? Возможно нет.
Неожиданно и интересно? Я так думаю.
Я бы начал с формулы
pi = 16 arctan (1/5) - 4 arctan (1/239)
Google легко найдет доказательство этой формулы, понятное обычным людям, и формулу для вычисления функции арктангенса. Это позволит вам легко и быстро вычислить несколько тысяч десятичных знаков числа пи.
Поскольку вы явно не указали, что ваша функция должна вычислять значения, вот возможное решение, если вы хотите иметь верхний предел количества цифр, которые она может "вычислить" эм>:
// 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 в пределах вашего верхнего предела.
Мои пять копеек... Это может быть не самым быстрым, но я думаю, что это довольно легко понять. Я придумал это сам во время лекции по математике и больше нигде в литературе не встречал. Либо я гений, совсем тупой, либо не особо обращаю внимание на чтение книг по математике, либо все вышеперечисленное... :)
В любом случае... Начните с единичного круга. Мы знаем, что x^2+y^2=1, поэтому y=sqrt(1-x^2). Мы также знаем, что площадь единичного круга равна PI. Если мы теперь возьмем интеграл функции sqrt(1-x^2) в диапазоне от 0 до 1, мы получим четверть PI. Умножьте это на 4, чтобы получить 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 правильных знаков после запятой. Не самый эффективный, но это мое детище... :)
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
.