Mi a leggyorsabb módja annak, hogy az értéke π?

szavazat
275

Keresem a leggyorsabb módja annak, hogy megkapjuk az értéke π, személyes kihívásnak. Pontosabban, az általam használt módszereket, amelyek nem járnak a #definekonstansok, mint pl M_PI, vagy a kódban a számot.

A program az alábbi tesztekben különböző módokon tudok. Az inline szerelés változat elméletileg leggyorsabb opció, bár nyilvánvalóan nem hordozhatók. Én már bele, mint egy kiindulási összehasonlítani a többi változat. Az én tesztek, beépített modulok, a 4 * atan(1)verzió leggyorsabb GCC 4.2, mert az automatikus bedobja atan(1)egy állandó. A -fno-builtinmegadva, a atan2(0, -1)változat a leggyorsabb.

Itt a fő vizsgálati program ( 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;
}

És inline szerelvény dolgot ( fldpi.c), hogy csak akkor fog működni x86 és x64 rendszerekhez:

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

És egy szkriptet, amely épít a konfigurációk Letesztelem ( 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

Eltekintve teszteli a különböző fordító zászlók (én képest 32 bites ellen 64 bites is, mert az optimalizálás különböző), én is próbáltam váltás az, hogy a vizsgálatok körül. De mégis, a atan2(0, -1)verzió még mindig jön ki győztesen minden alkalommal.

A kérdést 01/08/2008 06:21
a forrás felhasználó
Más nyelveken...                            


23 válasz

szavazat
180

A Monte Carlo módszer , mint már említettük, érvényes néhány nagy elképzelések, de ez nyilvánvalóan nem a leggyorsabb, nem pedig egy hosszú lövés, nem bármilyen ésszerű intézkedést. Továbbá, minden attól függ, hogy milyen pontossággal, amit keres. A leggyorsabb π tudok az, aki a számjegyek nehéz kódolni. Nézzük Pi és Pi [PDF] , van egy csomó képleteket.

Itt van egy módszer, amely konvergál gyorsan - mintegy 14 számjegy egy ciklus. PiFast , a jelenlegi leggyorsabb alkalmazás használja ezt a képletet az FFT . Én csak írni a képlet, hiszen a kód egyszerű. Ez a képlet majdnem talált Ramanujan és által felfedezett Chudnovsky . Ez valójában hogyan számítják több milliárd számjegyét - így ez nem egy módszer, hogy figyelmen kívül hagyja. A képlet kifut és gyorsan, hiszen az osztódó faktoriális, előnyös lenne akkor, hogy késleltesse az ilyen számításokat eltávolítani feltételeket.

írja kép leírása itt

írja kép leírása itt

hol,

írja kép leírása itt

Az alábbiakban a Brent-Salamin algoritmus . Wikipedia említi, hogy amikor a és b jelentése „elég közel”, majd (a + b) ² / 4t lesz közelítése π. Nem tudom, mit jelent a „elég közel” azt jelenti, de az én teszt, egy iterációs kapott 2 számjegy, két kapott 7 és három volt 15, természetesen ez a páros, így lehet, hogy egy hiba alapuló képviselet és az igazi számítás lehetne pontosabb.

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)

Végül, mit szólnál egy kis pi golf (800 szám)? 160 karakter!

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);}
Válaszolt 02/08/2008 19:22
a forrás felhasználó

szavazat
96

Nagyon szeretem ezt a programot, amely megközelíti a pi nézi saját területén :-)

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()
{
            _-_-_-_
       _-_-_-_-_-_-_-_-_
    _-_-_-_-_-_-_-_-_-_-_-_
  _-_-_-_-_-_-_-_-_-_-_-_-_-_
 _-_-_-_-_-_-_-_-_-_-_-_-_-_-_
 _-_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
 _-_-_-_-_-_-_-_-_-_-_-_-_-_-_
 _-_-_-_-_-_-_-_-_-_-_-_-_-_-_
  _-_-_-_-_-_-_-_-_-_-_-_-_-_
    _-_-_-_-_-_-_-_-_-_-_-_
        _-_-_-_-_-_-_-_
            _-_-_-_
}
Válaszolt 02/09/2008 14:28
a forrás felhasználó

szavazat
72

Itt egy általános leírást a technika kiszámításához pi, hogy tanultam a középiskolában.

Csak ossza meg ezt, mert szerintem ez elég egyszerű, hogy bárki is emlékszik rá, a végtelenségig, ráadásul tanít meg a „Monte-Carlo” módszerek - melyek statisztikai módszerek érkező válaszok, amelyek nem jelennek meg azonnal, hogy levezethető a véletlenszerű folyamatokat.

Négyzet rajzolásához és beírását egy kvadráns (egynegyede félkör) belül, hogy a négyzet alakú (a kvadráns sugárral egyenlő a oldalán a tér, így kitölti annyi a négyzet, mint lehetséges)

Most dobja a dart a téren, és rögzíti, amikor földet ér - azaz, válasszon egy véletlenszerűen kiválasztott ponton belül bárhova a téren. Persze, leszállt a szögletes, de ez benne a félkör? Jegyezze fel ezt a tényt.

Ismételjük ezt a folyamatot többször - és meg fogja találni az aránya a pontok száma belüli félkör szemben az összes dobott, hívja ezt az arányt x.

Mivel a terület a tér r-szer r, akkor arra következtethetünk, hogy a terület a félig kör x-szer r alkalommal r (azaz x-szer R a négyzeten). Ezért x alkalommal 4 kapsz pi.

Ez nem egy gyors módszer használható. De ez egy szép példa a Monte Carlo módszerrel. És ha körülnézünk, akkor előfordulhat, hogy sok probléma egyébként ezen kívül a számítógépes készségek lehet megoldani az ilyen módszereket.

Válaszolt 01/08/2008 14:37
a forrás felhasználó

szavazat
51

A teljesség kedvéért, a C ++ template változat, amely az optimalizált építmények kiszámolja PI fordítási időben és inline egyetlen érték.

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

Megjegyzés I> 10, az optimális épít lassú lehet, hasonlóképpen a nem optimalizált fut. 12 ismétléseket Úgy vélem, vannak körül 80k hívások értéke () (hiányában memoisation).

Válaszolt 22/12/2009 16:40
a forrás felhasználó

szavazat
40

Itt tulajdonképpen egy egész könyvet szentelt (többek között), hogy gyorsan módszerek számításának \ pi: "Pi és az AGM, Jonathan és Peter Borwein ( elérhető az Amazon ).

Tanulmányoztam a közgyűlés és a kapcsolódó algoritmusok egy kicsit: ez egy elég érdekes (bár néha nem triviális).

Figyeljük meg, hogy, hogy végre a legtöbb modern algoritmusok kiszámítására \ pi, szüksége lesz egy többszörös pontosságú aritmetikai könyvtár ( GMP elég jó választás, bár már egy ideje, mióta utoljára használtam).

Az idő-bonyolultsága a legjobb algoritmusok O (M (n) log (n)), ahol M (n) az idő-bonyolultsága a szorzás a két N-bites egészek (M (n) = O (n log (n) log (log (n))) segítségével FFT-alapú algoritmusok, amelyeket általában akkor szükséges, ha a számítási számjegye \ pi, és egy ilyen algoritmus van megvalósítva GMP).

Megjegyzendő, hogy bár a matematika mögött az algoritmusok lehet, hogy nem triviális, az algoritmusok maguk általában néhány sornyi pszeudo-kód és megvalósításuk általában nagyon egyszerű (ha úgy döntött, hogy nem írhatunk többszörös pontosságú aritmetika :-)).

Válaszolt 24/08/2008 18:14
a forrás felhasználó

szavazat
36

A következő választ , hogy pontosan hogyan kell ezt csinálni a lehető leggyorsabb módon - a legkisebb számítási erőfeszítés . Még ha nem tetszik a válasz, akkor el kell ismernem, hogy valóban a leggyorsabb módja annak , hogy a pi értékét.

A leggyorsabb módja , hogy az érték a Pi:

  1. úgy döntött, a kedvenc programozási nyelv
  2. betölteni azt a matematikai könyvtár
  3. és kiderül, hogy Pi már ott meghatározott !! készen arra, hogy használni ..

abban az esetben, ha nem rendelkezik a matematikai könyvtár kéznél ..

A második leggyorsabban módon (több univerzális megoldás) a következő:

felnéz Pi az interneten, pl itt:

http://www.eveandersson.com/pi/digits/1000000 (1 millió számjegy .. mi a lebegőpontos pontosság?)

vagy itt:

http://3.141592653589793238462643383279502884197169399375105820974944592.com/

vagy itt:

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

Ez nagyon gyorsan megtalálja a számjegyek szükség van bármilyen pontosságú aritmetika szeretne használni, és meghatározunk egy állandó, biztos lehet benne, hogy nem pazarolja az értékes CPU időt.

Nem csak ez részben humoros választ, de a valóságban, ha bárki is megy előre, és kiszámítja a pi értékét egy valós alkalmazás .. lenne egy elég nagy hulladék CPU idő, nem igaz? Legalábbis én nem látok igazi kérelem próbálja újra kiszámolja ezt.

Kedves Moderátor: Kérjük, vegye figyelembe, hogy az OP megkérdezte: „leggyorsabb út , hogy a pi értékét”

Válaszolt 28/10/2011 02:02
a forrás felhasználó

szavazat
25

A BBP képlet lehetővé teszi, hogy kiszámolja az n-edik számjegy - a bázis 2 (vagy 16) - anélkül, hogy még akkor is zavarja az előző n-1 számjegy első :)

Válaszolt 29/08/2008 10:22
a forrás felhasználó

szavazat
21

Ahelyett, pi, mint egy állandó, mindig használni acos(-1).

Válaszolt 08/03/2009 04:02
a forrás felhasználó

szavazat
20

Ha ez a cikk igaz, akkor az algoritmus, amely Bellard teremtett egyike lehet a leggyorsabb elérhető. Ő hozta létre a pi 2,7 billió számjegy egy asztali PC!

... és ő adta ki dolgozik itt

Jó munkát Bellard, Ön egy úttörő!

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

Válaszolt 06/01/2010 13:41
a forrás felhasználó

szavazat
20

Csak jött át ez az egyik, hogy itt kell lennie a teljesség:

számítani PI Piet

Ez a meglehetősen szép tulajdonság, hogy a pontosság javítható így a program nagyobb.

Itt „s némi betekintést a nyelv maga

Válaszolt 12/01/2009 19:46
a forrás felhasználó

szavazat
19

Ez egy „klasszikus” módszer, nagyon könnyen megvalósítható. Ez a megvalósítás, a python (nem olyan gyorsan nyelven) csinálja:

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)

Bővebb információ itt .

Egyébként a leggyorsabb módja, hogy egy precíz, sok-as-you-akarom pi értékét a python:

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

itt a darab forrása a gmpy pi módszer, nem hiszem, hogy a kód annyira hasznos, mint a megjegyzés ebben az esetben:

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: Volt néhány probléma kivágás és beillesztés és identation, egyébként megtalálja a forrást itt .

Válaszolt 02/10/2008 22:27
a forrás felhasználó

szavazat
17

Ha a leggyorsabb érted leggyorsabb, hogy írja be a kódot, itt a golfscript megoldás:

;''6666,-2%{2+.2/@*\/10.3??2*+}*`1000<~\;
Válaszolt 06/08/2008 23:54
a forrás felhasználó

szavazat
15

A Machin-szerű képletű

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.

Megvalósult reakcióvázlat, például:

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

Válaszolt 05/02/2011 06:26
a forrás felhasználó

szavazat
15

A páros:

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

Ez lesz pontos legfeljebb 14 tizedesjegy pontossággal, elég kitölteni egy dupla (a pontatlanság valószínűleg azért, mert a többi tizedesjegyek ív érintők csonka).

Szintén Seth, ez 3.14159265358979323846 3 , nem 64.

Válaszolt 28/02/2010 04:52
a forrás felhasználó

szavazat
15

Ha hajlandó használni közelítés, 355 / 113jó 6 tizedesjegy, és az az előnye, hogy használható legyen egész kifejezéseket. Ez nem olyan fontos manapság, mint „lebegőpontos matematikai társprocesszor” megszűnt nincs értelme, de ez igen fontos volt egyszerre.

Válaszolt 17/09/2009 17:30
a forrás felhasználó

szavazat
15

Pi pontosan 3! [Prof. Frink (Simpson)]

Vicc, de itt van egy C # (.NET Framework-szükséges).

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;
        }
    }
}
Válaszolt 26/02/2009 20:22
a forrás felhasználó

szavazat
15

Számítsuk ki a PI fordításkor a D.

(Átmásolja 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))) );
Válaszolt 17/09/2008 18:49
a forrás felhasználó

szavazat
13

Ez a verzió (Delphi) semmi különös, de legalább gyorsabb, mint a változat Nick Hodge írt blogjában :). A gépemen, ez kb 16 másodperc, hogy csinál egy milliárd ismétléseket, így értéke 3,14159265 25879 (a pontos része van szedve).

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.
Válaszolt 12/01/2009 19:24
a forrás felhasználó

szavazat
12

Ha azt szeretnénk, hogy számítani közelítő értéke π (valamilyen okból), meg kell próbálnia a bináris extrakciós algoritmus. Bellard féle javítása BBP ad nem PI O (n ^ 2).


Ha azt szeretnénk, hogy kapjunk egy közelítő értékének π csinálni számítások, akkor:

PI = 3.141592654

Nyújtott, ez csak egy becslés, és nem teljesen pontos. Ez ki egy kicsit több, mint ,00000000004102. (négy ten-trillionths, mintegy 4 / 10000000000 ).


Ha azt szeretnénk, hogy nem matematikai és π, akkor kap magának egy papírt és ceruzát, vagy egy számítógépes algebrai csomagot, és használja π pontos értéket π.

Ha szeretné egy formula, ez egy szórakoztató:

π = - i Ln (-1)

Válaszolt 22/12/2009 22:13
a forrás felhasználó

szavazat
12

Vissza a régi időkben, a kis szó méretű és lassú vagy nem létező lebegőpontos műveleteket, szoktuk csinálni dolgokat, mint ez:

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

Az olyan alkalmazások, amelyek nem igényelnek sok precíziós (videojátékok, például), ez nagyon gyors, és elég pontos.

Válaszolt 20/02/2009 22:21
a forrás felhasználó

szavazat
11

Brent módszere küldte fent Chris nagyon jó; Brent általában egy óriás területén a tetszőleges pontosságú aritmetika.

Ha az összes kívánt az N. számjegyet, a híres BBP formula hasznos hex

Válaszolt 04/08/2009 22:39
a forrás felhasználó

szavazat
1

Kiszámítása π körből területen :-)

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

Válaszolt 03/06/2017 17:13
a forrás felhasználó

szavazat
0

jobb megközelítés

Ahhoz, hogy a kimeneti szabvány állandók, mint pi vagy a standard fogalmak, akkor először megy a builtins módszer áll rendelkezésre az a nyelv, amit használ. Vissza fog térni az értéket a leggyorsabb és legjobb módja is. Én használ python, hogy a leggyorsabb módja annak, hogy az értéket pi

  • pi változó a matematikai könyvtár . Matematikai könyvtár tárolja a változó pi állandónak.

math_pi.py

import math
print math.pi

Futtassa a szkriptet idő hasznosságát linux /usr/bin/time -v python math_pi.py

output:

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
  • Használja arc cos eljárás matematikai

acos_pi.py

import math
print math.acos(-1)

Futtassa a szkriptet idő hasznosságát linux /usr/bin/time -v python acos_pi.py

output:

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

Futtassa a szkriptet idő hasznosságát linux /usr/bin/time -v python bbp_pi.py

output:

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

Tehát a legjobb módja az, hogy builtins eljárás által biztosított nyelvi mert ők a leggyorsabb és a legjobb, hogy a kimenetet. A python használat Math.PI

Válaszolt 18/06/2018 10:07
a forrás felhasználó

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more