Jaki jest najszybszy sposób na uzyskanie wartości π?

Szukam najszybszego sposobu, aby uzyskać wartość π, jako osobiste wyzwanie. Dokładniej, używam sposobów, które nie wymagają używania stałych #define, takich jak M_PI, lub kodowania na twardo liczby w.

Poniższy program testuje różne sposoby, jakie znam. Wersja do montażu liniowego jest teoretycznie najszybszą opcją, choć wyraźnie nie jest przenośna. Umieściłem go jako podstawę do porównania z innymi wersjami. W moich testach, z wbudowanymi, wersja 4 * atan(1) jest najszybsza na GCC 4.2, ponieważ automatycznie składa atan(1) do stałej. Jeśli podano -fno-builtin, Wersja atan2(0, -1) jest najszybsza.

Oto główny program testowy (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;
}
[10]}), które będą działać tylko dla systemów x86 i x64:
double
fldpi()
{
    double pi;
    asm("fldpi" : "=t" (pi));
    return pi;
}

I skrypt build, który buduje wszystkie konfiguracje, które testuję (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

Oprócz testowania pomiędzy różnymi flagami kompilatora (porównałem też 32-bit z 64-bitem, ponieważ optymalizacje są różne), próbowałem też zmienić kolejność testów. Ale wersja atan2(0, -1) wciąż wychodzi na wierzch za każdym razem.

Author: Chris Jester-Young, 2008-08-01

23 answers

Metoda Monte Carlo , Jak wspomniano, stosuje kilka świetnych koncepcji, ale oczywiście nie jest najszybsza, nie na dłuższą metę, nie na żadną rozsądną miarę. Ponadto wszystko zależy od tego, jakiego rodzaju dokładności szukasz. Najszybszy π jaki znam to ten z mocno zakodowanymi cyframi. Patrząc na Pi i Pi [PDF] , istnieje wiele wzorów.

Oto metoda, która szybko się zbiega - około 14 cyfr na iterację. PiFast , obecny najszybsza aplikacja, używa tej formuły z FFT. Napiszę tylko formułę, ponieważ kod jest prosty. Ta formuła została prawie znaleziona przez Ramanujan i odkryta przez Chudnovsky . Tak właśnie obliczył kilka miliardów cyfr liczby - więc nie jest to metoda do lekceważenia. Wzór szybko się przepełni i skoro dzielimy faktorie, to korzystne byłoby opóźnienie takich obliczeń w celu usunięcia warunki.

Tutaj wpisz opis obrazka

Tutaj wpisz opis obrazka

Gdzie,

Tutaj wpisz opis obrazka

Poniżej znajduje się algorytm Brenta–Salamina . Wikipedia wspomina, że gdy a i b są "wystarczająco blisko", to (A + b)2 / 4T będzie przybliżeniem π. Nie jestem pewien co oznacza "wystarczająco blisko", ale z moich testów, jedna iteracja ma 2 cyfry, dwie ma 7, a trzy ma 15, oczywiście jest to z dublami, więc może mieć błąd na podstawie jego reprezentacji i true obliczenia mogą być dokładniejsze.

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)
Na koniec może Pi golf (800 cyfr)? 160 znaków!
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);}
 189
Author: nlucaroni,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-05 11:46:23

Bardzo podoba mi się ten program, ponieważ przybliża π patrząc na jego własny obszar.

1988: westleyc
#define _ -F<00||--F-OO--;
int F=00,OO=00;main(){F_OO();printf("%1.3f\n",4.*-F/OO/OO);}F_OO()
{
            _-_-_-_
       _-_-_-_-_-_-_-_-_
    _-_-_-_-_-_-_-_-_-_-_-_
  _-_-_-_-_-_-_-_-_-_-_-_-_-_
 _-_-_-_-_-_-_-_-_-_-_-_-_-_-_
 _-_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
 _-_-_-_-_-_-_-_-_-_-_-_-_-_-_
 _-_-_-_-_-_-_-_-_-_-_-_-_-_-_
  _-_-_-_-_-_-_-_-_-_-_-_-_-_
    _-_-_-_-_-_-_-_-_-_-_-_
        _-_-_-_-_-_-_-_
            _-_-_-_
}
 100
Author: Pat,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-03 05:27:55

Oto ogólny opis techniki obliczania pi, której nauczyłem się w liceum.

Podzielam to tylko dlatego, że myślę, że jest to na tyle proste, że każdy może to zapamiętać, w nieskończoność, Plus uczy cię pojęcia "metody Monte-Carlo" - które są statystycznymi metodami uzyskiwania odpowiedzi, które nie wydają się natychmiast dedukcyjne poprzez procesy losowe.

Narysuj kwadrant i wpisz kwadrant (jedną czwartą półkola) wewnątrz tego kwadratu (a kwadrant o promieniu równym boku kwadratu, więc wypełnia jak najwięcej kwadratu)

Teraz rzuć strzałką w kwadrat i zapisz, gdzie wyląduje - to znaczy wybierz losowy punkt w dowolnym miejscu wewnątrz kwadratu. Oczywiście wylądował wewnątrz kwadratu, ale czy jest wewnątrz półkola? Nagraj ten fakt.

Powtórz ten proces wiele razy - a zobaczysz, że jest stosunek liczby punktów wewnątrz półkola do całkowitej liczby rzuconych, zadzwoń do tego stosunku x.

Ponieważ powierzchnia kwadratu jest R razy r, można wywnioskować, że powierzchnia półkola jest x razy r razy r (czyli x razy R do kwadratu). Stąd x razy 4 daje pi.

Nie jest to szybka metoda w użyciu. Ale to dobry przykład metody Monte Carlo. A jeśli rozejrzysz się dookoła, może się okazać, że wiele problemów poza twoimi umiejętnościami obliczeniowymi może zostać rozwiązanych za pomocą takich metod.

 76
Author: Leon Bambrick,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-05-25 21:09:03

W trosce o kompletność, wersja szablonu C++, która dla zoptymalizowanego kompilacji będzie obliczać PI w czasie kompilacji i będzie wbudowana do pojedynczej wartości.

#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;
}

Uwaga dla I > 10, zoptymalizowane Kompilacje mogą być powolne, podobnie w przypadku nie zoptymalizowanych uruchomień. Dla 12 iteracji uważam, że jest około 80K wywołań do value () (w przypadku braku memoizacji).

 51
Author: jon-hanson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-02 13:19:52

Istnieje właściwie cała książka poświęcona (między innymi) szybkim metodom obliczania \pi: 'Pi i AGM', autorstwa Jonathana i Petera Borweinów (dostępna na Amazon).

Trochę przestudiowałem AGM i powiązane algorytmy: jest to dość interesujące (choć czasami nietrywialne).

Zauważ, że aby zaimplementować większość nowoczesnych algorytmów do obliczania \pi, będziesz potrzebował wieloprecyzyjnej biblioteki arytmetycznej (GMP jest całkiem dobrym wyborem, chociaż jest minęło trochę czasu, odkąd ostatni raz go używałem).

Złożoność czasowa najlepszych algorytmów jest w O (M (n) log(n)), gdzie M (N) jest złożonością czasową dla mnożenia dwóch N-bitowych liczb całkowitych(m(n)=O(N log(n) log(log (n))) przy użyciu algorytmów opartych na FFT, które są zwykle potrzebne przy obliczaniu cyfr \pi, A taki algorytm jest zaimplementowany w GMP).

Zauważ, że chociaż matematyka stojąca za algorytmami może nie być trywialna, same algorytmy są zwykle kilkoma linijkami pseudo-kod, a ich implementacja jest zazwyczaj bardzo prosta (jeśli nie zdecydowałeś się na pisanie własnej arytmetyki wieloprecyzyjnej: -)).

 40
Author: OysterD,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-01-06 00:48:57

Następujące odpowiedzi dokładnie jak to zrobić w najszybszy możliwy sposób -- przy najmniejszym wysiłku obliczeniowym. Nawet jeśli nie podoba Ci się odpowiedź, musisz przyznać, że jest to najszybszy sposób, aby uzyskać wartość PI.

Najszybszym sposobem uzyskania wartości Pi jest:

  1. wybierz swój ulubiony język programowania
  2. load it ' s Math library
  3. i znaleźć, że Pi jest już zdefiniowany tam!! gotowy do użycia to..

W przypadku, gdy nie masz biblioteki Matematycznej pod ręką..

The SECOND FASTEST way (bardziej uniwersalne rozwiązanie) is:

Poszukaj Pi w Internecie, np. tutaj:

Http://www.eveandersson.com/pi/digits/1000000 (1 milion cyfr .. jaka jest twoja zmiennoprzecinkowa precyzja? )

Lub tutaj:

Http://3.141592653589793238462643383279502884197169399375105820974944592.com/

Lub tutaj:

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

To naprawdę szybko znaleźć cyfry, których potrzebujesz do dowolnej arytmetyki precyzji chcesz użyć, a definiując stałą, możesz upewnić się, że nie marnujesz cennego czasu procesora.

Nie tylko jest to częściowo humorystyczna odpowiedź, ale w rzeczywistości, jeśli ktoś mógłby przejść do przodu i obliczyć wartość Pi w prawdziwej aplikacji .. to byłaby spora strata czasu procesora, prawda? Przynajmniej nie widzę prawdziwego aplikacja do próby ponownego obliczenia tego.

Drogi Moderatorze: proszę pamiętać, że OP zapytał: "najszybszy sposób , aby uzyskać wartość PI"

 37
Author: Tilo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-05-25 21:13:02

Formuła BBP pozwala obliczyć n-tą cyfrę-w bazie 2 (lub 16) - bez konieczności zawracania sobie głowy poprzednimi N-1 cyframi:)

 25
Author: Tyler,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-08-29 09:22:16

Zamiast definiować pi jako stałą, zawsze używam acos(-1).

 21
Author: Peter Mortensen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-05-25 21:11:11

Właśnie natknąłem się na ten, który powinien być tutaj dla kompletności:

Oblicz PI w Piet

Ma dość ładną właściwość, że precyzja może być poprawiona, dzięki czemu program jest większy.

Tutaj ' s some insight into the language himself

 20
Author: krusty.ar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-19 13:32:19

Jeśli Ten artykuł jest prawdziwy, to algorytm stworzony przez Bellarda może być jednym z najszybszych dostępnych. Stworzył pi do 2,7 biliona cyfr za pomocą komputera stacjonarnego!

...i opublikował tutaj Swoją pracę

Dobra robota Bellard, jesteś pionierem!

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

 20
Author: Mark Cooper,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-01-06 12:46:03

Jest to "klasyczna" metoda, bardzo łatwa do wdrożenia. Ta implementacja w Pythonie (nie tak szybkim języku) robi to:

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)

Więcej informacji znajdziesz tutaj .

W każdym razie najszybszym sposobem uzyskania dokładnej wartości pi w Pythonie jest:

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

Oto fragment źródła dla metody gmpy pi, nie sądzę, aby Kod był tak przydatny jak komentarz w tym przypadku:

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: miałem jakiś problem z cięciem i wklej i identacja, w każdym razie źródło znajdziesz tutaj .

 19
Author: Andrea Ambu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-02 22:11:35

Jeśli przez najszybszy masz na myśli najszybszy wpisanie kodu, oto rozwiązanie golfscript :

;''6666,-2%{2+.2/@*\/10.3??2*+}*`1000<~\;
 17
Author: Michiel de Mare,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-08-06 22:54:12

Użyj wzoru Machinopodobnego

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.

Zaimplementowane w Scheme, na przykład:

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

 16
Author: NihilistDandy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-11-19 22:39:49

Pi jest dokładnie 3! [Prof. Frink (Simpsonowie)]

Żart, ale tutaj jest jeden w C# (. Net-Framework wymagane).

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;
        }
    }
}
 15
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-02-26 19:22:22

Jeśli chcesz użyć przybliżenia, 355 / 113 jest dobry dla 6 cyfr dziesiętnych i ma dodatkową zaletę, że można go używać z wyrażeniami całkowitymi. To nie jest tak ważne w dzisiejszych czasach, jak "zmiennoprzecinkowy koprocesor matematyczny" przestał mieć jakiekolwiek znaczenie, ale kiedyś był dość ważny.

 15
Author: Daniel C. Sobral,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-09-17 16:30:44

Z podwójnymi:

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

To będzie dokładne do 14 miejsc po przecinku, wystarczająco, aby wypełnić podwójną (niedokładność wynika prawdopodobnie z tego, że reszta miejsc po przecinku w stycznych łuku jest obcięta).

Również Seth, to 3.141592653589793238463, nie 64.

 15
Author: qwerty01,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-05-25 21:12:06

Oblicz PI w czasie kompilacji z D.

( skopiowane z 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))) );
 15
Author: Brad Gilbert,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-02-27 15:13:26

Ta wersja (w Delphi) nie jest niczym szczególnym, ale jest co najmniej szybsza od wersji, którą Nick Hodge zamieścił na swoim blogu:). Na mojej maszynie wykonanie miliarda iteracji zajmuje około 16 sekund, co daje wartość 3.1415926525879 (dokładna część jest pogrubiona).

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.
 13
Author: JosephStyons,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-12 18:30:06

W dawnych czasach, przy małych rozmiarach słów i powolnych lub nieistniejących operacjach zmiennoprzecinkowych, robiliśmy takie rzeczy:

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

W przypadku aplikacji, które nie wymagają dużej precyzji (na przykład gier wideo), jest to bardzo szybkie i wystarczająco dokładne.

 12
Author: Kristopher Johnson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-02-20 21:26:34

Jeśli chcesz obliczyć przybliżenie wartości π (z jakiegoś powodu), powinieneś wypróbować algorytm ekstrakcji binarnej. Bellard ' s Poprawa BBP daje do PI w O (N^2).


Jeśli chcesz uzyskać przybliżenie wartości π do wykonania obliczeń, to:

PI = 3.141592654
To tylko przybliżenie i nie do końca dokładne. Jest o nieco więcej niż 0.00000000004102. (cztery dziesięciozgłoskowce, o 4/10,000,000,000).

Jeśli chcesz zrobić matematykę z π, kup sobie ołówek i papier lub pakiet algebry komputerowej i użyj dokładnej wartości π, π.

Jeśli naprawdę chcesz formułę, ta jest fajna:

Π = - i ln (-1)

 12
Author: Seth,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-12-22 21:13:49

Metoda Brenta opublikowana powyżej przez Chrisa jest bardzo dobra; Brent ogólnie jest gigantem w dziedzinie arytmetyki arbitralnie precyzyjnej.

Jeśli wszystko czego chcesz to N-ta cyfra, słynny Formuła BBP jest przydatny w hex

 11
Author: James Youngman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-08-04 21:39:13

Obliczanie π z obszaru okręgu: -)

<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>
 1
Author: Agnius Vasiliauskas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-04 16:53:53

Lepsze Podejście

Aby uzyskać wyjście stałych standardowych, takich jak pi lub standardowych pojęć, powinniśmy najpierw przejść do metod builtins dostępnych w języku, którego używasz. Zwróci wartość w najszybszy i najlepszy sposób. Używam Pythona, aby uzyskać najszybszy sposób uzyskania wartości pi

  • zmienna pi biblioteki matematycznej . Biblioteka matematyczna przechowuje zmienną pi jako stałą.

Math_pi.py

import math
print math.pi

Run skrypt z time utility of linux /usr/bin/time -v python math_pi.py

Wyjście:

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
  • użyj metody Arc cos w matematyce

Acos_pi.py

import math
print math.acos(-1)

Uruchom skrypt z time utility of linux /usr/bin/time -v python acos_pi.py

Wyjście:

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

Uruchom skrypt z time utility of linux /usr/bin/time -v python bbp_pi.py

Wyjście:

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

Więc najlepszym sposobem jest użycie metody builtins dostarczone przez język powodują, że są one najszybsze i najlepsze do uzyskania wyjścia. W Pythonie użyj matematyki.pi

 0
Author: anand tripathi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-18 10:07:01