performance - Quel est le moyen le plus rapide pour obtenir la valeur de π?

Translate

Je recherche le moyen le plus rapide d'obtenir la valeur de π, en tant que défi personnel. Plus précisément, j'utilise des moyens qui n'impliquent pas l'utilisation#defineconstantes commeM_PI, ou coder le nombre en dur.

Le programme ci-dessous teste les différentes façons dont je connais. La version d'assemblage en ligne est, en théorie, l'option la plus rapide, bien que clairement non portable. Je l'ai inclus comme référence pour comparer avec les autres versions. Dans mes tests, avec des éléments intégrés, le4 * atan(1)version est la plus rapide sur GCC 4.2, car elle replie automatiquement leatan(1)en une constante. Avec-fno-builtinspécifié, leatan2(0, -1)la version est la plus rapide.

Voici le programme de test principal (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;
}

Et les trucs d'assemblage en ligne (fldpi.c) qui ne fonctionnera que pour les systèmes x86 et x64:

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

Et un script de construction qui construit toutes les configurations que je teste (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

Outre les tests entre divers indicateurs de compilateur (j'ai également comparé le 32 bits à 64 bits car les optimisations sont différentes), j'ai également essayé de changer l'ordre des tests. Mais encore, leatan2(0, -1)la version est toujours en tête à chaque fois.

This question and all comments follow the "Attribution Required."

Toutes les réponses

Translate

leMéthode de Monte Carlo, comme mentionné, applique de grands concepts, mais ce n'est clairement pas le plus rapide, ni de loin, ni par aucune mesure raisonnable. De plus, tout dépend du type de précision que vous recherchez. Le π le plus rapide que je connaisse est celui dont les chiffres sont codés en dur. RegarderPietPi [PDF], il existe de nombreuses formules.

Voici une méthode qui converge rapidement - environ 14 chiffres par itération.PiFast, l'application la plus rapide actuellement, utilise cette formule avec la FFT. Je vais juste écrire la formule, car le code est simple. Cette formule a été presque trouvée parRamanujan et découvert par Chudnovsky. C'est en fait ainsi qu'il a calculé plusieurs milliards de chiffres du nombre - ce n'est donc pas une méthode à ignorer. La formule débordera rapidement et, puisque nous divisons les factorielles, il serait alors avantageux de retarder ces calculs pour supprimer les termes.

enter image description here

enter image description here

où,

enter image description here

Ci-dessous leAlgorithme de Brent – Salamin. Wikipédia mentionne que lorsqueaetbsont "assez proches" alors(a + b) ² / 4tsera une approximation de π. Je ne suis pas sûr de ce que signifie «assez proche», mais d'après mes tests, une itération a eu 2 chiffres, 2 7 et 3 15, bien sûr, c'est avec des doubles, donc il peut y avoir une erreur basée sur sa représentation et lavraile calcul pourrait être plus précis.

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)

Enfin, que diriez-vous du golf pi (800 chiffres)? 160 caractères!

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);}
La source
Pat
Translate

J'aime vraiment ce programme, car il se rapproche de π en regardant sa propre zone.

IOCCC 1988:westley.c

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

Voici une description générale d'une technique de calcul de pi que j'ai apprise au lycée.

Je ne partage cela que parce que je pense que c'est assez simple pour que tout le monde puisse s'en souvenir, indéfiniment, et cela vous enseigne le concept des méthodes "Monte-Carlo" - qui sont des méthodes statistiques pour arriver à des réponses qui ne semblent pas déductibles par des processus aléatoires.

Dessinez un carré et inscrivez un quadrant (un quart de demi-cercle) à l'intérieur de ce carré (un quadrant de rayon égal au côté du carré, de sorte qu'il remplisse autant que possible le carré)

Maintenant, lancez une fléchette sur la case et enregistrez où elle atterrit - c'est-à-dire, choisissez un point aléatoire n'importe où dans la case. Bien sûr, il a atterri à l'intérieur du carré, mais est-ce à l'intérieur du demi-cercle? Enregistrez ce fait.

Répétez ce processus plusieurs fois - et vous constaterez qu'il existe un rapport entre le nombre de points à l'intérieur du demi-cercle et le nombre total lancé, appelez ce rapport x.

Puisque l'aire du carré est r fois r, vous pouvez en déduire que l'aire du demi-cercle est x fois r fois r (c'est-à-dire x fois r au carré). Par conséquent, x fois 4 vous donnera pi.

Ce n'est pas une méthode rapide à utiliser. Mais c'est un bel exemple de méthode de Monte Carlo. Et si vous regardez autour de vous, vous constaterez peut-être que de nombreux problèmes autres que vos compétences en calcul peuvent être résolus par de telles méthodes.

La source
Translate

Dans un souci d'exhaustivité, une version de modèle C ++, qui, pour une construction optimisée, calculera une approximation de PI au moment de la compilation, et sera intégrée à une valeur unique.

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

Remarque pour I> 10, les builds optimisés peuvent être lents, de même pour les exécutions non optimisées. Pour 12 itérations, je crois qu'il y a environ 80k appels à value () (en l'absence de mémoisation).

La source
Translate

Il y a en fait un livre entier dédié (entre autres) àviteméthodes pour le calcul de \ pi: 'Pi et l'AGA', par Jonathan et Peter Borwein (disponible sur Amazon).

J'ai beaucoup étudié l'AGM et les algorithmes associés: c'est assez intéressant (bien que parfois non trivial).

Notez que pour implémenter la plupart des algorithmes modernes pour calculer \ pi, vous aurez besoin d'une bibliothèque arithmétique multiprécision (GMPest un bon choix, même si cela fait un moment que je ne l'ai pas utilisé pour la dernière fois).

La complexité temporelle des meilleurs algorithmes est en O (M (n) log (n)), où M (n) est la complexité temporelle pour la multiplication de deux entiers de n bits (M (n) = O (n log (n) log (log (n))) en utilisant des algorithmes basés sur FFT, qui sont généralement nécessaires lors du calcul des chiffres de \ pi, et un tel algorithme est implémenté dans GMP).

Notez que même si les mathématiques derrière les algorithmes peuvent ne pas être triviales, les algorithmes eux-mêmes ne sont généralement que quelques lignes de pseudo-code, et leur implémentation est généralement très simple (si vous avez choisi de ne pas écrire votre propre arithmétique multiprécision :-)).

La source
Translate

Les réponses suivantesprécisément comment faire cela de la manière la plus rapide possible - avec le moins d'effort de calcul. Même si vous n'aimez pas la réponse, vous devez admettre que c'est en effet le moyen le plus rapide d'obtenir la valeur de PI.

leLE PLUS RAPIDELa façon d'obtenir la valeur de Pi est:

1) choisissez votre langage de programmation préféré 2) chargez sa bibliothèque Math 3) et constatez que Pi y est déjà défini - prêt à l'emploi!

Si vous n'avez pas de bibliothèque mathématique à portée de main.

leDEUXIÈME PLUS RAPIDEmanière (solution plus universelle) est:

recherchez Pi sur Internet, par exemple ici:

http://www.eveandersson.com/pi/digits/1000000(1 million de chiffres ... quelle est votre précision en virgule flottante?)

ou ici:

http://3.141592653589793238462643383279502884197169399375105820974944592.com/

ou ici:

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

Il est très rapide de trouver les chiffres dont vous avez besoin pour l'arithmétique de précision que vous souhaitez utiliser, et en définissant une constante, vous pouvez vous assurer de ne pas perdre de temps précieux sur le processeur.

Non seulement c'est une réponse en partie humoristique, mais en réalité, si quelqu'un allait de l'avant et calculait la valeur de Pi dans une application réelle ... ce serait une assez grosse perte de temps CPU, n'est-ce pas? Au moins, je ne vois pas de vraie application pour essayer de recalculer cela.

Cher modérateur, veuillez noter que l'OP a demandé: "Le moyen le plus rapide d'obtenir la valeur de PI"

La source
Translate

leFormule BBPvous permet de calculer le nième chiffre - en base 2 (ou 16) - sans même avoir à vous soucier des n-1 chiffres précédents :)

La source
Elvira Lee
Translate

Au lieu de définir pi comme une constante, j'utilise toujoursacos(-1).

La source
Translate

Je viens de tomber sur celui-ci qui devrait être ici pour être complet:

calculer PI en Piet

Il a la propriété plutôt intéressante que la précision peut être améliorée en rendant le programme plus grand.

Icia un aperçu de la langue elle-même

La source
Translate

SiCet articleest vrai, alors lealgorithme que Bellarda créé pourrait être l'un des plus rapides disponibles. Il a créé pi à 2,7 TRILLIONS de chiffres en utilisant un PC DE BUREAU!

... et il a publié sontravaille ici

Bon travail Bellard, vous êtes un pionnier!

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

La source
Translate

Il s'agit d'une méthode "classique", très simple à mettre en œuvre. Cette implémentation, en python (langage pas si rapide) le fait:

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)

Vous pouvez trouver plus d'informationsici.

Quoi qu'il en soit, le moyen le plus rapide d'obtenir une valeur précise de pi autant que vous le souhaitez en python est:

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

voici le morceau de source pour la méthode gmpy pi, je ne pense pas que le code soit aussi utile que le commentaire dans ce cas:

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

ÉDITER:J'ai eu un problème avec le copier-coller et l'identification, de toute façon vous pouvez trouver la sourceici.

La source
Translate

Si par plus rapide vous voulez dire plus rapide pour taper le code, voici legolfscriptSolution:

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

Utilisez la formule de type 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.

Implémenté dans Scheme, par exemple:

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

La source
Montague Lee
Translate

Si vous souhaitez utiliser une approximation,355 / 113convient pour 6 chiffres décimaux et présente l'avantage supplémentaire d'être utilisable avec des expressions entières. Ce n'est pas aussi important de nos jours, car «coprocesseur mathématique en virgule flottante» a cessé d'avoir un sens, mais c'était assez important une fois.

La source
Translate

Avec doubles:

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

Ce sera précis jusqu'à 14 décimales, assez pour remplir un double (l'imprécision est probablement due au fait que le reste des décimales dans les tangentes de l'arc sont tronquées).

Aussi Seth, c'est 3.141592653589793238463, pas 64.

La source
Translate

Calculez PI au moment de la compilation avec D.

(Copié depuisDSource.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))) );
La source
Translate

Pi est exactement 3! [Prof. Frink (Simpsons)]

Blague, mais en voici une en C # (.NET-Framework requis).

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;
        }
    }
}
La source
Translate

Cette version (en Delphi) n'a rien de spécial, mais elle est au moins plus rapide quela version publiée par Nick Hodge sur son blog:). Sur ma machine, il faut environ 16 secondes pour effectuer un milliard d'itérations, soit une valeur de3,1415926525879 (la partie exacte est en gras).

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.
La source
Translate

À l'époque, avec des mots de petite taille et des opérations en virgule flottante lentes ou inexistantes, nous avions l'habitude de faire des choses comme ceci:

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

Pour les applications qui ne nécessitent pas beaucoup de précision (jeux vidéo par exemple), c'est très rapide et suffisamment précis.

La source
Translate

Si tu veuxcalculerune approximation de la valeur de π (pour une raison quelconque), vous devriez essayer un algorithme d'extraction binaire.Bellardamélioration deBBPdonne PI dans O (N ^ 2).


Si tu veuxobtenirune approximation de la valeur de π pour faire des calculs, alors:

PI = 3.141592654

Certes, ce n'est qu'une approximation et pas tout à fait exacte. Il est décalé d'un peu plus de 0,0000000000004102. (quatre dix mille milliards, environ4/10 000 000 000).


Si tu veux fairemathavec π, puis procurez-vous un crayon et du papier ou un paquet d'algèbre informatique, et utilisez la valeur exacte de π, π.

Si vous voulez vraiment une formule, celle-ci est amusante:

π = -iln (-1)

La source
Translate

La méthode de Brent publiée ci-dessus par Chris est très bonne; Brent est généralement un géant dans le domaine de l'arithmétique à précision arbitraire.

Si tout ce que vous voulez est le Nième chiffre, le fameuxFormule BBPest utile en hexadécimal

La source
Translate

Calculer π à partir de l'aire du cercle :-)

<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>
La source
Translate

Meilleure approche

Pour obtenir la sortie de constantes standard commepiou les concepts standard, nous devons d'abord utiliser les méthodes intégrées disponibles dans le langage que vous utilisez. Il renverra de la valeur de la manière la plus rapide et la meilleure également. J'utilise python pour obtenir le moyen le plus rapide d'obtenir la valeur pi

  • variable pi de la bibliothèque mathématique. La bibliothèque mathématique stocke la variable pi comme constante.

math_pi.py

import math
print math.pi

Exécutez le script avec l'utilitaire de temps de Linux/usr/bin/time -v python math_pi.py

Production:

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
  • Utiliser la méthode mathématique arc cos

acos_pi.py

import math
print math.acos(-1)

Exécutez le script avec l'utilitaire de temps de Linux/usr/bin/time -v python acos_pi.py

Production:

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

Exécutez le script avec l'utilitaire de temps de Linux/usr/bin/time -v python bbp_pi.py

Production:

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

La meilleure façon est donc d'utiliser la méthode intégrée fournie par le langage car elle est la plus rapide et la meilleure pour obtenir la sortie. En python, utilisez math.pi

La source