Какой самый быстрый способ получить значение π?

Я ищу самый быстрый способ получить значение π, как личный вызов. Более конкретно, я использую способы, которые не включают использование #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("%st=> %e, time => %fn", #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-битным, потому что оптимизация отличается), я также попытался переключить порядок тестов. Но все же ... --8--> версия по-прежнему выходит на первое место каждый раз.

23 ответов


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

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

enter image description here

enter image description here

здесь

enter image description here

ниже Брент–Саламин. Википедия упоминает об этом, когда a и b "достаточно близко" тогда ² a + b) 2 / 4t будет приближением π. Я не уверен, что означает "достаточно близко", но из моих тестов одна итерация получила 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)

наконец, как насчет некоторых Pi golf (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);}

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

IOCCC 1988 : Уэстли.c

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

вот общее описание методики расчета pi, которую я изучал в средней школе.

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

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

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

повторите этот процесс много раз - и вы обнаружите, что существует отношение количества точек внутри полукруга к общему число брошено, назовем это отношение x.

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

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


в интересах полноты, версия шаблона 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 итераций я считаю, что есть около 80k вызовов value () (при отсутствии memoisation).


на самом деле есть целая книга, посвященная (среди прочего)быстро методы вычисления \pi: 'Pi и AGM', Джонатан и Питер Борвейн ( доступно на Amazon).

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

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

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

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


ответы именно как это сделать самым быстрым способом - с наименьшими вычислительными усилиями. Даже если вам не нравится ответ, вы должны признать, что это действительно самый быстрый способ get значение PI.

на самый быстрый способ чтобы получить значение Pi:

  1. выберите свой любимый язык программирования
  2. загрузить это математическая библиотека
  3. и найти, что Pi уже определились там!! готов к использованию..

в случае, если у вас нет математической библиотеки под рукой..

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

посмотрите Pi в Интернете, например, здесь:

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

или здесь:

http://3.141592653589793238462643383279502884197169399375105820974944592.com/

или здесь:

http://en.wikipedia.org/wiki/Pi

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

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

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


на BBP формула позволяет вычислить N-ю цифру-в базе 2 (или 16)-без необходимости даже беспокоиться о предыдущих N-1 цифр сначала:)


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


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

вычислить PI в Piet

Он имеет достаточно приятное свойство, что точность может быть улучшена, делая ярче.

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


Если в этой статье истинно, то алгоритм, который Bellard создал может быть одним из самых быстрых доступных. Он создал pi до 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;
}

EDIT: у меня были некоторые проблемы с вырезать и вставить и identation, в любом случае вы можете найти источник здесь.


Если под самым быстрым вы подразумеваете самый быстрый для ввода кода, вот golfscript устранение:

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

используйте машинную формулу

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))))


Pi ровно 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;
        }
    }
}

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


дубли:

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

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

также сет, это 3.141592653589793238463, а не 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))) );

эта версия (в 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)

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


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


Если вы хотите получить аппроксимация значения π для выполнения вычислений, то:

PI = 3.141592654

конечно, это только приближение и не совсем точное. Это немного больше, чем 0.00000000004102. (четыре десяти-триллионную, о 4/10,000,000,000).


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

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

π = -Я ln (-1)


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

Если все, что вам нужно, это N-я цифра, знаменитая BBP формула полезно в hex


вычисление π из области окружности: -)

<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>

Лучше

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

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

math_pi.py

import math
print math.pi

запустите скрипт с помощью утилиты time в 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 math

acos_pi.py

import math
print math.acos(-1)

запустите скрипт с помощью утилиты time в 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))

запустите скрипт с помощью утилиты time в 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

поэтому лучший способ-использовать метод builtins, предоставляемый языком, потому что они являются самыми быстрыми и лучшими для получения вывода. В python используйте математику.Пи