Вопрос

Я ищу самый быстрый способ получить значение π как личный вызов.Точнее, я использую способы, не связанные с использованием #define константы, такие как M_PI, или жестко запрограммировать число.

В приведенной ниже программе тестируются различные известные мне способы.Теоретически встроенная ассемблерная версия является самым быстрым вариантом, хотя она явно не переносима.Я включил его в качестве основы для сравнения с другими версиями.В моих тестах со встроенными модулями 4 * atan(1) версия является самой быстрой на GCC 4.2, поскольку она автоматически сворачивает atan(1) в константу.С -fno-builtin указано, atan2(0, -1) версия самая быстрая.

Вот основная программа тестирования (pitimes.c):

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

#define ITERS 10000000
#define TESTWITH(x) {                                                       \
    diff = 0.0;                                                             \
    time1 = clock();                                                        \
    for (i = 0; i < ITERS; ++i)                                             \
        diff += (x) - M_PI;                                                 \
    time2 = clock();                                                        \
    printf("%s\t=> %e, time => %f\n", #x, diff, diffclock(time2, time1));   \
}

static inline double
diffclock(clock_t time1, clock_t time0)
{
    return (double) (time1 - time0) / CLOCKS_PER_SEC;
}

int
main()
{
    int i;
    clock_t time1, time2;
    double diff;

    /* Warmup. The atan2 case catches GCC's atan folding (which would
     * optimise the ``4 * atan(1) - M_PI'' to a no-op), if -fno-builtin
     * is not used. */
    TESTWITH(4 * atan(1))
    TESTWITH(4 * atan2(1, 1))

#if defined(__GNUC__) && (defined(__i386__) || defined(__amd64__))
    extern double fldpi();
    TESTWITH(fldpi())
#endif

    /* Actual tests start here. */
    TESTWITH(atan2(0, -1))
    TESTWITH(acos(-1))
    TESTWITH(2 * asin(1))
    TESTWITH(4 * atan2(1, 1))
    TESTWITH(4 * atan(1))

    return 0;
}

И встроенная сборка (fldpi.c), который будет работать только для систем x86 и x64:

double
fldpi()
{
    double pi;
    asm("fldpi" : "=t" (pi));
    return pi;
}

И скрипт сборки, который собирает все тестируемые мной конфигурации (build.sh):

#!/bin/sh
gcc -O3 -Wall -c           -m32 -o fldpi-32.o fldpi.c
gcc -O3 -Wall -c           -m64 -o fldpi-64.o fldpi.c

gcc -O3 -Wall -ffast-math  -m32 -o pitimes1-32 pitimes.c fldpi-32.o
gcc -O3 -Wall              -m32 -o pitimes2-32 pitimes.c fldpi-32.o -lm
gcc -O3 -Wall -fno-builtin -m32 -o pitimes3-32 pitimes.c fldpi-32.o -lm
gcc -O3 -Wall -ffast-math  -m64 -o pitimes1-64 pitimes.c fldpi-64.o -lm
gcc -O3 -Wall              -m64 -o pitimes2-64 pitimes.c fldpi-64.o -lm
gcc -O3 -Wall -fno-builtin -m64 -o pitimes3-64 pitimes.c fldpi-64.o -lm

Помимо тестирования различных флагов компилятора (я также сравнивал 32-битные и 64-битные версии, поскольку оптимизации различаются), я также пробовал менять порядок тестов.Но тем не менее, atan2(0, -1) версия по-прежнему каждый раз выходит на первое место.

Это было полезно?

Решение

А Метод Монте-Карло, Как уже упоминалось, он применяет некоторые замечательные концепции, но он явно не самый быстрый, ни в долгосрочной перспективе, ни по каким-либо разумным меркам.Кроме того, все зависит от того, какую точность вы ищете.Самое быстрое число π, которое я знаю, — это число с жестко запрограммированными цифрами.Смотря на Пи и Пи[PDF], формул очень много.

Вот метод, который сходится быстро — около 14 цифр на итерацию. ПиФаст, самое быстрое на данный момент приложение, использует эту формулу вместе с БПФ.Я просто напишу формулу, так как код простой.Эту формулу почти нашел Рамануджана и открыт Чудновским..На самом деле именно так он вычислил несколько миллиардов цифр числа — так что этим методом нельзя пренебрегать.Формула быстро переполнится, и, поскольку мы делим факториалы, было бы выгодно отложить такие вычисления, чтобы удалить члены.

enter image description here

enter image description here

где,

enter image description here

Ниже приведен Алгоритм Брента – Саламина.В Википедии упоминается, что когда а и б тогда они "достаточно близки" (а + б)² / 4т будет приближением π.Я не уверен, что означает «достаточно близко», но по моим тестам одна итерация получила 2 цифры, две - 7, а три - 15, конечно, это с двойными числами, поэтому может быть ошибка, основанная на ее представлении и тот истинный расчет мог бы быть более точным.

let pi_2 iters =
    let rec loop_ a b t p i =
        if i = 0 then a,b,t,p
        else
            let a_n = (a +. b) /. 2.0 
            and b_n = sqrt (a*.b)
            and p_n = 2.0 *. p in
            let t_n = t -. (p *. (a -. a_n) *. (a -. a_n)) in
            loop_ a_n b_n t_n p_n (i - 1)
    in 
    let a,b,t,p = loop_ (1.0) (1.0 /. (sqrt 2.0)) (1.0/.4.0) (1.0) iters in
    (a +. b) *. (a +. b) /. (4.0 *. t)

И наконец, как насчет пи-гольфа (800 цифр)?160 символов!

int a=10000,b,c=2800,d,e,f[2801],g;main(){for(;b-c;)f[b++]=a/5;for(;d=0,g=c*2;c-=14,printf("%.4d",e+d/a),e=d%a)for(b=c;d+=f[b]*a,f[b]=d%--g,d/=g--,--b;d*=b);}

Другие советы

Мне очень нравится эта программа, потому что она аппроксимирует число π, глядя на свою площадь.

МОККЦ 1988: Уэстли.с

#define _ -F<00||--F-OO--;
int F=00,OO=00;main(){F_OO();printf("%1.3f\n",4.*-F/OO/OO);}F_OO()
{
            _-_-_-_
       _-_-_-_-_-_-_-_-_
    _-_-_-_-_-_-_-_-_-_-_-_
  _-_-_-_-_-_-_-_-_-_-_-_-_-_
 _-_-_-_-_-_-_-_-_-_-_-_-_-_-_
 _-_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
 _-_-_-_-_-_-_-_-_-_-_-_-_-_-_
 _-_-_-_-_-_-_-_-_-_-_-_-_-_-_
  _-_-_-_-_-_-_-_-_-_-_-_-_-_
    _-_-_-_-_-_-_-_-_-_-_-_
        _-_-_-_-_-_-_-_
            _-_-_-_
}

Вот общее описание метода вычисления числа Пи, которому я научился в старшей школе.

Я делюсь этим только потому, что считаю, что это достаточно просто, чтобы каждый мог запомнить это на неопределенный срок, плюс это учит вас концепции методов «Монте-Карло», которые представляют собой статистические методы получения ответов, которые не сразу кажутся верными. выводимые посредством случайных процессов.

Нарисуйте квадрат и впишите в него квадрант (четверть полукруга) (квадрант с радиусом, равным стороне квадрата, чтобы он занимал как можно большую часть квадрата)

Теперь бросьте дротик в квадрат и запишите, где он приземлится, то есть выберите случайную точку в любом месте внутри квадрата.Конечно, он приземлился внутри квадрата, но внутри ли полукруга?Зафиксируйте этот факт.

Повторите этот процесс много раз — и вы обнаружите, что существует соотношение количества точек внутри полукруга к общему количеству брошенных мячей, назовите это соотношение х.

Поскольку площадь квадрата равна r, умноженная на r, вы можете сделать вывод, что площадь полукруга равна x, умноженному на r, умноженному на r (то есть, x, умноженному на r в квадрате).Следовательно, x, умноженное на 4, даст вам число Пи.

Это не быстрый метод.Но это хороший пример метода Монте-Карло.И если вы посмотрите вокруг, вы можете обнаружить, что многие проблемы, выходящие за рамки ваших вычислительных навыков, могут быть решены с помощью таких методов.

В целях полноты, версия шаблона C++, которая для оптимизированной сборки будет вычислять приблизительное значение PI во время компиляции и встраиваться в одно значение.

#include <iostream>

template<int I>
struct sign
{
    enum {value = (I % 2) == 0 ? 1 : -1};
};

template<int I, int J>
struct pi_calc
{
    inline static double value ()
    {
        return (pi_calc<I-1, J>::value () + pi_calc<I-1, J+1>::value ()) / 2.0;
    }
};

template<int J>
struct pi_calc<0, J>
{
    inline static double value ()
    {
        return (sign<J>::value * 4.0) / (2.0 * J + 1.0) + pi_calc<0, J-1>::value ();
    }
};


template<>
struct pi_calc<0, 0>
{
    inline static double value ()
    {
        return 4.0;
    }
};

template<int I>
struct pi
{
    inline static double value ()
    {
        return pi_calc<I, I>::value ();
    }
};

int main ()
{
    std::cout.precision (12);

    const double pi_value = pi<10>::value ();

    std::cout << "pi ~ " << pi_value << std::endl;

    return 0;
}

Обратите внимание, что при I > 10 оптимизированные сборки могут быть медленными, как и при неоптимизированных запусках.Я считаю, что за 12 итераций происходит около 80 тысяч вызовов value() (при отсутствии мемоизации).

На самом деле существует целая книга, посвященная (среди прочего) быстрый методы вычисления \pi:«Пи и годовое собрание», Джонатан и Питер Борвейны (доступен на Амазоне).

Я довольно много изучил AGM и связанные с ним алгоритмы:это довольно интересно (хотя местами и нетривиально).

Обратите внимание, что для реализации большинства современных алгоритмов вычисления \pi вам понадобится арифметическая библиотека с множественной точностью (GMP вполне хороший выбор, хотя я уже давно им не пользовался).

Временная сложность лучших алгоритмов составляет O(M(n)log(n)), где M(n) — временная сложность умножения двух n-битных целых чисел (M(n)=O(n log(n) log(log(n))) с использованием алгоритмов на основе БПФ, которые обычно необходимы при вычислении цифр \pi, и такой алгоритм реализован в GMP).

Обратите внимание: хотя математика, лежащая в основе алгоритмов, может быть нетривиальной, сами алгоритмы обычно представляют собой несколько строк псевдокода, и их реализация обычно очень проста (если вы решили не писать свою собственную арифметику с множественной точностью :-)).

Следующие ответы как это сделать максимально быстро и с наименьшими вычислительными затратами.Даже если вам не нравится ответ, вы должны признать, что это действительно самый быстрый способ получить значение ПИ.

А САМЫЙ БЫСТРЫЙ способ получить значение Пи:

1) Выберите свой любимый язык программирования 2) Загрузите его математическую библиотеку 3) и обнаружите, что PI уже определен там - готова к использованию!

Если у вас нет под рукой библиотеки Math..

А ВТОРОЙ БЫСТРЫЙ способ (более универсальное решение):

найдите число Пи в Интернете, например.здесь:

http://www.evandersson.com/pi/digits/1000000 (1 миллион цифр..какова ваша точность с плавающей запятой?)

или здесь:

http://3.141592653589793238462643383279502884197169399375105820974944592.com/

или здесь:

http://en.wikipedia.org/wiki/Пи

Найти нужные цифры для любой точной арифметики можно очень быстро, а определив константу, вы можете быть уверены, что не тратите драгоценное время процессора.

Мало того, что это отчасти юмористический ответ, но на самом деле, если бы кто-нибудь пошел дальше и вычислил значение числа Пи в реальном приложении...это было бы довольно большой тратой процессорного времени, не так ли?По крайней мере, я не вижу реального применения для попыток пересчитать это.

Уважаемый модератор:обратите внимание, что ОП спросил:«Самый быстрый способ получить значение PI»

А Формула ББП позволяет вычислить n-ю цифру - по основанию 2 (или 16) - даже не заморачиваясь сначала с предыдущими цифрами n-1 :)

Вместо того, чтобы определять число Пи как константу, я всегда использую acos(-1).

Только что наткнулся на вот это, которое должно быть здесь для полноты картины:

рассчитать PI в Piet

У него есть довольно приятное свойство: точность можно повысить, увеличив размер программы.

Здесьнемного понимания самого языка

Если Эта статья верно, то алгоритм, который Беллард созданный может быть одним из самых быстрых из доступных.Он создал число Пи, состоящее из 2,7 ТРИЛЛИОНОВ цифр, используя НАСТОЛЬНЫЙ ПК!

...и он опубликовал свою работать здесь

Молодец, Беллард, ты пионер!

http://www.theregister.co.uk/2010/01/06/very_long_pi/

Это «классический» метод, очень простой в реализации.Эта реализация на Python (не такой быстрый язык) делает это:

from math import pi
from time import time


precision = 10**6 # higher value -> higher precision
                  # lower  value -> higher speed

t = time()

calc = 0
for k in xrange(0, precision):
    calc += ((-1)**k) / (2*k+1.)
calc *= 4. # this is just a little optimization

t = time()-t

print "Calculated: %.40f" % calc
print "Costant pi: %.40f" % pi
print "Difference: %.40f" % abs(calc-pi)
print "Time elapsed: %s" % repr(t)

Вы можете найти дополнительную информацию здесь.

В любом случае самый быстрый способ получить точное значение числа pi в Python:

from gmpy import pi
print pi(3000) # the rule is the same as 
               # the precision on the previous code

вот фрагмент исходного кода метода gmpy pi, я не думаю, что в этом случае код так же полезен, как комментарий:

static char doc_pi[]="\
pi(n): returns pi with n bits of precision in an mpf object\n\
";

/* This function was originally from netlib, package bmp, by
 * Richard P. Brent. Paulo Cesar Pereira de Andrade converted
 * it to C and used it in his LISP interpreter.
 *
 * Original comments:
 * 
 *   sets mp pi = 3.14159... to the available precision.
 *   uses the gauss-legendre algorithm.
 *   this method requires time o(ln(t)m(t)), so it is slower
 *   than mppi if m(t) = o(t**2), but would be faster for
 *   large t if a faster multiplication algorithm were used
 *   (see comments in mpmul).
 *   for a description of the method, see - multiple-precision
 *   zero-finding and the complexity of elementary function
 *   evaluation (by r. p. brent), in analytic computational
 *   complexity (edited by j. f. traub), academic press, 1976, 151-176.
 *   rounding options not implemented, no guard digits used.
*/
static PyObject *
Pygmpy_pi(PyObject *self, PyObject *args)
{
    PympfObject *pi;
    int precision;
    mpf_t r_i2, r_i3, r_i4;
    mpf_t ix;

    ONE_ARG("pi", "i", &precision);
    if(!(pi = Pympf_new(precision))) {
        return NULL;
    }

    mpf_set_si(pi->f, 1);

    mpf_init(ix);
    mpf_set_ui(ix, 1);

    mpf_init2(r_i2, precision);

    mpf_init2(r_i3, precision);
    mpf_set_d(r_i3, 0.25);

    mpf_init2(r_i4, precision);
    mpf_set_d(r_i4, 0.5);
    mpf_sqrt(r_i4, r_i4);

    for (;;) {
        mpf_set(r_i2, pi->f);
        mpf_add(pi->f, pi->f, r_i4);
        mpf_div_ui(pi->f, pi->f, 2);
        mpf_mul(r_i4, r_i2, r_i4);
        mpf_sub(r_i2, pi->f, r_i2);
        mpf_mul(r_i2, r_i2, r_i2);
        mpf_mul(r_i2, r_i2, ix);
        mpf_sub(r_i3, r_i3, r_i2);
        mpf_sqrt(r_i4, r_i4);
        mpf_mul_ui(ix, ix, 2);
        /* Check for convergence */
        if (!(mpf_cmp_si(r_i2, 0) && 
              mpf_get_prec(r_i2) >= (unsigned)precision)) {
            mpf_mul(pi->f, pi->f, r_i4);
            mpf_div(pi->f, pi->f, r_i3);
            break;
        }
    }

    mpf_clear(ix);
    mpf_clear(r_i2);
    mpf_clear(r_i3);
    mpf_clear(r_i4);

    return (PyObject*)pi;
}

РЕДАКТИРОВАТЬ: У меня были проблемы с вырезанием, вставкой и идентификацией, в любом случае вы можете найти источник здесь.

Если под самым быстрым вы имеете в виду самый быстрый ввод кода, вот гольфскрипт решение:

;''6666,-2%{2+.2/@*\/10.3??2*+}*`1000<~\;

Используйте формулу типа Machin

176 * arctan (1/57) + 28 * arctan (1/239) - 48 * arctan (1/682) + 96 * arctan(1/12943) 

[; \left( 176 \arctan \frac{1}{57} + 28 \arctan \frac{1}{239} - 48 \arctan \frac{1}{682} + 96 \arctan \frac{1}{12943}\right) ;], for you TeX the World people.

Реализовано в схеме, например:

(+ (- (+ (* 176 (atan (/ 1 57))) (* 28 (atan (/ 1 239)))) (* 48 (atan (/ 1 682)))) (* 96 (atan (/ 1 12943))))

Если вы готовы использовать приближение, 355 / 113 подходит для 6 десятичных цифр и имеет дополнительное преимущество: его можно использовать с целочисленными выражениями.В наши дни это не так важно, поскольку «математический сопроцессор с плавающей запятой» перестал иметь какое-либо значение, но когда-то это было весьма важно.

С двойками:

4.0 * (4.0 * Math.Atan(0.2) - Math.Atan(1.0 / 239.0))

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

Еще Сет, это 3.14159265358979323846.3, а не 64.

Рассчитайте PI во время компиляции с помощью D.

(Скопировано с DSource.org )

/** Calculate pi at compile time
 *
 * Compile with dmd -c pi.d
 */
module calcpi;

import meta.math;
import meta.conv;

/** real evaluateSeries!(real x, real metafunction!(real y, int n) term)
 *
 * Evaluate a power series at compile time.
 *
 * Given a metafunction of the form
 *  real term!(real y, int n),
 * which gives the nth term of a convergent series at the point y
 * (where the first term is n==1), and a real number x,
 * this metafunction calculates the infinite sum at the point x
 * by adding terms until the sum doesn't change any more.
 */
template evaluateSeries(real x, alias term, int n=1, real sumsofar=0.0)
{
  static if (n>1 && sumsofar == sumsofar + term!(x, n+1)) {
     const real evaluateSeries = sumsofar;
  } else {
     const real evaluateSeries = evaluateSeries!(x, term, n+1, sumsofar + term!(x, n));
  }
}

/*** Calculate atan(x) at compile time.
 *
 * Uses the Maclaurin formula
 *  atan(z) = z - z^3/3 + Z^5/5 - Z^7/7 + ...
 */
template atan(real z)
{
    const real atan = evaluateSeries!(z, atanTerm);
}

template atanTerm(real x, int n)
{
    const real atanTerm =  (n & 1 ? 1 : -1) * pow!(x, 2*n-1)/(2*n-1);
}

/// Machin's formula for pi
/// pi/4 = 4 atan(1/5) - atan(1/239).
pragma(msg, "PI = " ~ fcvt!(4.0 * (4*atan!(1/5.0) - atan!(1/239.0))) );

Пи равно 3![Проф.Фринк (Симпсоны)]

Шутка, но вот один на C# (требуется .NET-Framework).

using System;
using System.Text;

class Program {
    static void Main(string[] args) {
        int Digits = 100;

        BigNumber x = new BigNumber(Digits);
        BigNumber y = new BigNumber(Digits);
        x.ArcTan(16, 5);
        y.ArcTan(4, 239);
        x.Subtract(y);
        string pi = x.ToString();
        Console.WriteLine(pi);
    }
}

public class BigNumber {
    private UInt32[] number;
    private int size;
    private int maxDigits;

    public BigNumber(int maxDigits) {
        this.maxDigits = maxDigits;
        this.size = (int)Math.Ceiling((float)maxDigits * 0.104) + 2;
        number = new UInt32[size];
    }
    public BigNumber(int maxDigits, UInt32 intPart)
        : this(maxDigits) {
        number[0] = intPart;
        for (int i = 1; i < size; i++) {
            number[i] = 0;
        }
    }
    private void VerifySameSize(BigNumber value) {
        if (Object.ReferenceEquals(this, value))
            throw new Exception("BigNumbers cannot operate on themselves");
        if (value.size != this.size)
            throw new Exception("BigNumbers must have the same size");
    }

    public void Add(BigNumber value) {
        VerifySameSize(value);

        int index = size - 1;
        while (index >= 0 && value.number[index] == 0)
            index--;

        UInt32 carry = 0;
        while (index >= 0) {
            UInt64 result = (UInt64)number[index] +
                            value.number[index] + carry;
            number[index] = (UInt32)result;
            if (result >= 0x100000000U)
                carry = 1;
            else
                carry = 0;
            index--;
        }
    }
    public void Subtract(BigNumber value) {
        VerifySameSize(value);

        int index = size - 1;
        while (index >= 0 && value.number[index] == 0)
            index--;

        UInt32 borrow = 0;
        while (index >= 0) {
            UInt64 result = 0x100000000U + (UInt64)number[index] -
                            value.number[index] - borrow;
            number[index] = (UInt32)result;
            if (result >= 0x100000000U)
                borrow = 0;
            else
                borrow = 1;
            index--;
        }
    }
    public void Multiply(UInt32 value) {
        int index = size - 1;
        while (index >= 0 && number[index] == 0)
            index--;

        UInt32 carry = 0;
        while (index >= 0) {
            UInt64 result = (UInt64)number[index] * value + carry;
            number[index] = (UInt32)result;
            carry = (UInt32)(result >> 32);
            index--;
        }
    }
    public void Divide(UInt32 value) {
        int index = 0;
        while (index < size && number[index] == 0)
            index++;

        UInt32 carry = 0;
        while (index < size) {
            UInt64 result = number[index] + ((UInt64)carry << 32);
            number[index] = (UInt32)(result / (UInt64)value);
            carry = (UInt32)(result % (UInt64)value);
            index++;
        }
    }
    public void Assign(BigNumber value) {
        VerifySameSize(value);
        for (int i = 0; i < size; i++) {
            number[i] = value.number[i];
        }
    }

    public override string ToString() {
        BigNumber temp = new BigNumber(maxDigits);
        temp.Assign(this);

        StringBuilder sb = new StringBuilder();
        sb.Append(temp.number[0]);
        sb.Append(System.Globalization.CultureInfo.CurrentCulture.NumberFormat.CurrencyDecimalSeparator);

        int digitCount = 0;
        while (digitCount < maxDigits) {
            temp.number[0] = 0;
            temp.Multiply(100000);
            sb.AppendFormat("{0:D5}", temp.number[0]);
            digitCount += 5;
        }

        return sb.ToString();
    }
    public bool IsZero() {
        foreach (UInt32 item in number) {
            if (item != 0)
                return false;
        }
        return true;
    }

    public void ArcTan(UInt32 multiplicand, UInt32 reciprocal) {
        BigNumber X = new BigNumber(maxDigits, multiplicand);
        X.Divide(reciprocal);
        reciprocal *= reciprocal;

        this.Assign(X);

        BigNumber term = new BigNumber(maxDigits);
        UInt32 divisor = 1;
        bool subtractTerm = true;
        while (true) {
            X.Divide(reciprocal);
            term.Assign(X);
            divisor += 2;
            term.Divide(divisor);
            if (term.IsZero())
                break;

            if (subtractTerm)
                this.Subtract(term);
            else
                this.Add(term);
            subtractTerm = !subtractTerm;
        }
    }
}

В этой версии (на Delphi) нет ничего особенного, но она, по крайней мере, быстрее, чем версия, которую Ник Ходж разместил в своем блоге :).На моей машине выполнение миллиарда итераций занимает около 16 секунд, что дает значение 3.1415926525879 (точная часть выделена жирным шрифтом).

program calcpi;

{$APPTYPE CONSOLE}

uses
  SysUtils;

var
  start, finish: TDateTime;

function CalculatePi(iterations: integer): double;
var
  numerator, denominator, i: integer;
  sum: double;
begin
  {
  PI may be approximated with this formula:
  4 * (1 - 1/3 + 1/5 - 1/7 + 1/9 - 1/11 .......)
  //}
  numerator := 1;
  denominator := 1;
  sum := 0;
  for i := 1 to iterations do begin
    sum := sum + (numerator/denominator);
    denominator := denominator + 2;
    numerator := -numerator;
  end;
  Result := 4 * sum;
end;

begin
  try
    start := Now;
    WriteLn(FloatToStr(CalculatePi(StrToInt(ParamStr(1)))));
    finish := Now;
    WriteLn('Seconds:' + FormatDateTime('hh:mm:ss.zz',finish-start));
  except
    on E:Exception do
      Writeln(E.Classname, ': ', E.Message);
  end;
end.

Раньше, когда размеры слов были небольшими, а операции с плавающей запятой выполнялись медленно или вообще отсутствовали, мы делали такие вещи:

/* Return approximation of n * PI; n is integer */
#define pi_times(n) (((n) * 22) / 7)

Для приложений, которые не требуют большой точности (например, видеоигры), это происходит очень быстро и достаточно точно.

Если вы хотите вычислить приближение значения π (по какой-то причине), вам следует попробовать алгоритм двоичного извлечения. Белларда улучшение ББП дает PI за O(N^2).


Если вы хотите получать приближенное значение π для проведения расчетов, тогда:

PI = 3.141592654

Конечно, это лишь приближение и не совсем точное.Отклонение составляет чуть более 0,00000000004102.(четыре десятитриллионных, около 4/10,000,000,000).


Если вы хотите сделать математика с π, затем возьмите карандаш и бумагу или пакет компьютерной алгебры и используйте точное значение π, π.

Если вам действительно нужна формула, вот это интересно:

π = -я пер(-1)

Метод Брента, опубликованный Крисом выше, очень хорош;Брент вообще является гигантом в области арифметики произвольной точности.

Если все, что вам нужно, это N-я цифра, знаменитаяФормула ББПполезно в шестнадцатеричном формате

Вычисление π по площади круга :-)

<input id="range" type="range" min="10" max="960" value="10" step="50" oninput="calcPi()">
<br>
<div id="cont"></div>

<script>
function generateCircle(width) {
    var c = width/2;
    var delta = 1.0;
    var str = "";
    var xCount = 0;
    for (var x=0; x <= width; x++) {
        for (var y = 0; y <= width; y++) {
            var d = Math.sqrt((x-c)*(x-c) + (y-c)*(y-c));
            if (d > (width-1)/2) {
                str += '.';
            }
            else {
                xCount++;
                str += 'o';
            }
            str += "&nbsp;" 
        }
        str += "\n";
    }
    var pi = (xCount * 4) / (width * width);
    return [str, pi];
}

function calcPi() {
    var e = document.getElementById("cont");
    var width = document.getElementById("range").value;
    e.innerHTML = "<h4>Generating circle...</h4>";
    setTimeout(function() {
        var circ = generateCircle(width);
        e.innerHTML  = "<pre>" + "π = " + circ[1].toFixed(2) + "\n" + circ[0] +"</pre>";
    }, 200);
}
calcPi();
</script>

Лучший подход

Чтобы получить вывод стандартных констант, таких как Пи или стандартные концепции, нам следует сначала использовать встроенные методы, доступные в используемом вами языке.Он вернет ценность самым быстрым и лучшим способом.Я использую Python, чтобы получить самый быстрый способ получить значение пи.

  • переменная pi математической библиотеки.Математическая библиотека хранит переменную pi как константу.

math_pi.py

import math
print math.pi

Запустите скрипт с помощью утилиты времени Linux. /usr/bin/time -v python math_pi.py

Выход:

Command being timed: "python math_pi.py"
User time (seconds): 0.01
System time (seconds): 0.01
Percent of CPU this job got: 91%
Elapsed (wall clock) time (h:mm:ss or m:ss): 0:00.03
  • Используйте математический метод arc cos

acos_pi.py

import math
print math.acos(-1)

Запустите скрипт с помощью утилиты времени Linux. /usr/bin/time -v python acos_pi.py

Выход:

Command being timed: "python acos_pi.py"
User time (seconds): 0.02
System time (seconds): 0.01
Percent of CPU this job got: 94%
Elapsed (wall clock) time (h:mm:ss or m:ss): 0:00.03

bbp_pi.py

from decimal import Decimal, getcontext
getcontext().prec=100
print sum(1/Decimal(16)**k * 
          (Decimal(4)/(8*k+1) - 
           Decimal(2)/(8*k+4) - 
           Decimal(1)/(8*k+5) -
           Decimal(1)/(8*k+6)) for k in range(100))

Запустите скрипт с помощью утилиты времени Linux. /usr/bin/time -v python bbp_pi.py

Выход:

Command being timed: "python c.py"
User time (seconds): 0.05
System time (seconds): 0.01
Percent of CPU this job got: 98%
Elapsed (wall clock) time (h:mm:ss or m:ss): 0:00.06

Поэтому лучший способ — использовать встроенные методы, предоставляемые языком, поскольку они быстрее и лучше всего получают выходные данные.В Python используйте math.pi

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top