kzen.dev
  • Întrebări
  • Tag-uri
  • Utilizatori
Notificări
Recompense
Înregistrare
După înregistrare, veți primi notificări despre răspunsurile și comentariile la întrebările DVS.
Logare
Dacă aveţi deja un cont, autentificaţi-vă pentru a verifica notificările noi.
Aici vor fi recompensele pentru întrebările, răspunsurile și comentariile adăugate sau modificate.
Mai mult
Sursă
Editează
Chris Jester-Young
Chris Jester-Young
Question

Ceea ce este cel mai rapid mod de a obține valoarea π?

Am'm în căutarea pentru cel mai rapid mod de a obține valoarea lui π, ca pe o provocare personală. Mai precis, am'm, folosind metode care nu't implica utilizarea #define constante ca M_PI, sau hard-codare numărul în.

Programul de mai jos teste diferite moduri știu. Inline assembly versiune este, în teorie, cel mai rapid opțiune, deși în mod clar nu este portabil. Am'am inclus-o ca o referință pentru a compara împotriva altor versiuni. În testele mele, cu built-in-uri, 4 * atan(1) versiune este mai rapidă pe GCC 4.2, pentru că auto-falduri atan(1) într-o constantă. Cu-fno-internaspecificatatan2(0, -1)` versiune este mai rapidă.

Aici's principalul program de testare (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;
}

Și inline assembly chestii (fldpi.c), care va funcționa doar pentru sisteme x86 și x64:

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

Și de a construi script-ul care se bazează toate configurațiile I'm de testare (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

În afară de testare între diverse compilatorul (I'am comparat 32-bit împotriva 64-bit pentru că optimizările sunt diferite), am'am încercat, de asemenea, de comutare ordinea de teste în jurul valorii de. Dar totuși, atan2(0, -1) versiune mai iese pe partea de sus de fiecare dată.

313 2008-08-01T05:21:22+00:00 23
 OmG
OmG
Întrebarea editată 15 mai 2019 в 1:33
Programare
language-agnostic
performance
algorithm
unix
pi
Popular videos
The Great Gildersleeve: Gildy&#39;s New Car / Leroy Has the Flu / Gildy Needs a Hobby
The Great Gildersleeve: Gildy's New Car / Leroy Has the Flu / Gildy Needs a Hobby
10 ani în urmă
SIMULATORUL TOM SI JERRY! PISICA vs SORICEL!
SIMULATORUL TOM SI JERRY! PISICA vs SORICEL!
1 an în urmă
Adevaruri ascunse din razboi - partea 1/4
Adevaruri ascunse din razboi - partea 1/4
1 an în urmă
DE CE SĂ SPERI CÂND POȚI SĂ CREZI ? ÎNDRĂZNEȘTE SĂ FII ÎNȚELEPT !
DE CE SĂ SPERI CÂND POȚI SĂ CREZI ? ÎNDRĂZNEȘTE SĂ FII ÎNȚELEPT !
1 an în urmă
CELE MAI BUNE SETARI PENTRU FREE FIRE 2022! HEASHOT 🤯 EASY 💣
CELE MAI BUNE SETARI PENTRU FREE FIRE 2022! HEASHOT 🤯 EASY 💣
1 an în urmă
VOX POPULI. Cu sau fără căciulă pe ger?
VOX POPULI. Cu sau fără căciulă pe ger?
1 an în urmă
Rugaciunea Care Indeplineste Orice Dorinta Celui Ce O Rosteste
Rugaciunea Care Indeplineste Orice Dorinta Celui Ce O Rosteste
3 ani în urmă
Criptomoneda care poate fi mai valoroasă decât Bitcoin ! Pi Network
Criptomoneda care poate fi mai valoroasă decât Bitcoin ! Pi Network
2 ani în urmă
#TOP 5 Aplicatii pe care le folosesc sa fac #BANI #ONLINE (Android si iOS 2020-2021)
#TOP 5 Aplicatii pe care le folosesc sa fac #BANI #ONLINE (Android si iOS 2020-2021)
2 ani în urmă
ACESTA ESTE CEL MAI *CRINGE* EMOTE DIN JOC ?! FREE FIRE ROMANIA
ACESTA ESTE CEL MAI *CRINGE* EMOTE DIN JOC ?! FREE FIRE ROMANIA
1 an în urmă
Cum investești 1000€ în crypto (începători)
Cum investești 1000€ în crypto (începători)
2 ani în urmă
Cel mai retardat Mod pe Minecraft !
Cel mai retardat Mod pe Minecraft !
1 an în urmă
3X Deadlier Than Cancer &amp; Most People Don&#39;t Know They Have It
3X Deadlier Than Cancer & Most People Don't Know They Have It
3 ani în urmă
Cel mai zgomotos GLA AMG Editia 1! (Cel mai rapid...)
Cel mai zgomotos GLA AMG Editia 1! (Cel mai rapid...)
2 ani în urmă
Lesson 17: Using NJK-5002C Proximity Hall Sensor  | Arduino Step By Step Course
Lesson 17: Using NJK-5002C Proximity Hall Sensor | Arduino Step By Step Course
1 an în urmă
« Anterior
Următor »
Această întrebare are 1 răspuns în engleză, pentru a le citi, vă rugăm să vă logați.
Solution / Answer
 nlucaroni
nlucaroni
2 august 2008 в 6:22
2008-08-02T18:22:52+00:00
Mai mult
Sursă
Editează
#8406226

La metoda Monte Carlo, după cum sa menționat, se aplică unele mare de concepte, dar este, în mod clar, nu cel mai rapid, nu de o lovitură de lungă, nu de orice măsură rezonabilă. De asemenea, totul depinde de ce fel de precizie sunteți în căutarea pentru. Cel mai rapid π știu de este cel cu cifre greu codificate. Se uită la Pi și Pi[PDF], există o mulțime de formule.

Aici este o metodă care converge rapid — aproximativ 14 cifre fiecare iterație. PiFast, cel mai rapid aplicația, folosește această formulă cu FFT. Am'll scrie formula, deoarece codul este simplu. Această formulă a fost gasit aproape de Ramanujan și descoperit de Chudnovsky. Acesta este, de fapt cum a calculat de mai multe miliarde de cifre ale numărului — e't o metodă de a ignora. Formula va revărsa ușor și, din moment ce suntem împărțirea factorialele, ar fi avantajoasă atunci să amâne astfel de calcule pentru a elimina termeni.

introduceți descrierea imaginii aici

introduceți descrierea imaginii aici

în cazul în care,

introduceți descrierea imaginii aici

Mai jos este Brent–Salamin algoritmul. Wikipedia menționează că, atunci când o și b sunt "destul de aproape" atunci (a + b)² / 4t va fi o aproximare a lui π. Am'm nu sunt sigur ce "destul de aproape" înseamnă, dar din testele mele, o repetare a primit 2 cifre, două luat 7, iar trei au avut 15, desigur, acest lucru este cu dublu, deci ar putea fi o eroare, pe baza de reprezentare și adevărat calcul ar putea fi mai precisă.

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)

În cele din urmă, cum despre unele pi golf (800 cifre)? 160 de caractere!

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);}
 Tyfingr
Tyfingr
Răspuns editat 5 septembrie 2018 в 11:46
201
0
 Pat
Pat
2 septembrie 2008 в 1:28
2008-09-02T13:28:51+00:00
Mai mult
Sursă
Editează
#8406230

Îmi place foarte mult acest program, pentru că acesta aproximează π uitandu-se la propria sa zonă.

IOCCC 1988 : westley.c

define _ -F<00||--F-OO--;

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

113
0
Leon Bambrick
Leon Bambrick
1 august 2008 в 1:37
2008-08-01T13:37:59+00:00
Mai mult
Sursă
Editează
#8406225

Aici's-o descriere generală a unei tehnica de calcul pi care le-am învățat în liceu.

Vreau doar să împărtășească acest lucru pentru că eu cred că este destul de simplu că oricine poate să-l amintesc, pe termen nelimitat, plus că te învață conceptul de "Monte-Carlo" metode-care sunt metodele statistice de a ajunge la răspunsurile pe care don't apar imediat să fie dedus prin procese aleatorii.

Desenați un pătrat, și înscrie un cadran (un sfert de un semi-cerc) în interiorul pătrat (un arc de cerc cu raza egală cu latura pătratului, astfel încât umple cât mai mult din piața posibil)

Acum arunca o săgeată în pătrat, și de a înregistra în cazul în care acesta a terenurilor-care este, pentru a alege un punct oarecare oriunde în interiorul pătrat. Desigur, a aterizat în interiorul pătrat, dar este în semi-cerc? Să înregistreze acest fapt.

Repetați acest proces de mai multe ori ... și veți găsi acolo este un raport de numărul de puncte din interiorul semi-cerc față de numărul total aruncat, numim acest raport x.

Deoarece zona de pătrat este de r ori r, se poate deduce că zona de semi cerc este de x ori r ori r (care este, de x ori r pătrat). Prin urmare, x 4 ori va da pi.

Aceasta nu este o metodă rapidă de a utiliza. Dar's un frumos exemplu de metoda Monte Carlo. Și dacă te uiți în jur, s-ar putea găsi că multe probleme în caz contrar, în afara abilități de calcul pot fi rezolvate prin astfel de metode.

77
0
 jon-hanson
jon-hanson
22 decembrie 2009 в 3:40
2009-12-22T15:40:04+00:00
Mai mult
Sursă
Editează
#8406240

Din motive de exhaustivitate, un C++ versiunea șablon, care, pentru o construcție optimizată, se va calcula o aproximare de PI la compilare, și va inline la o singură valoare.

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

Notă pentru am > 10, optimizat construiește poate fi lentă, de asemenea, pentru non-optimizat ruleaza. Pentru 12 iterații cred că există în jur de 80k apeluri la valoarea() (în absența memoisation).

 jon-hanson
jon-hanson
Răspuns editat 26 decembrie 2018 в 9:38
55
0
 OysterD
OysterD
24 august 2008 в 5:14
2008-08-24T17:14:08+00:00
Mai mult
Sursă
Editează
#8406228

Nu's, de fapt, o carte întreagă dedicată (printre alte lucruri) a rapid metode de calcul al \pi: 'Pi și AGM', de Jonathan și Peter Borwein (disponibil pe Amazon).

Am studiat AGM și legate de algoritmi destul de un pic: it's destul de interesant (deși, uneori, non-trivial).

Rețineți că, pentru a implementa cele mai moderne algoritmi pentru a calcula \pi, veți avea nevoie de un multiprecision biblioteca aritmetică (GMP este destul de o alegere bună, deși l's a fost un timp de când nu am mai folosit-o).

Ora-complexitate dintre cele mai bune algoritmi este în O(M(n)log(n)), unde M(n) este timpul de complexitate pentru înmulțirea a două n-bit numere întregi (M(n)=O(n log(n) log(log(n))), folosind FFT pe baza de algoritmi, care sunt de obicei necesare atunci când se calculează cifrele de \pi, și un astfel de algoritm este implementat în GMP).

Rețineți că, chiar dacă matematica din spatele algoritmilor-ar putea să nu fie banal, algoritmii ei înșiși sunt, de obicei, câteva linii de pseudo-cod, și punerea lor în aplicare este de obicei foarte simplă (dacă ați ales să nu scrie propriile multiprecision aritmetică :-) ).

43
0
 Tilo
Tilo
28 octombrie 2011 в 1:02
2011-10-28T01:02:09+00:00
Mai mult
Sursă
Editează
#8406245

Următoarele răspunsuri exact cum să facă acest lucru în cel mai rapid mod posibil-cu puțin efort de calcul. Chiar dacă tu nu't ca răspuns, trebuie să recunosc că este într-adevăr cel mai rapid mod de a obține valoarea lui PI.

La RAPID mod pentru a obține valoarea lui Pi este:

  1. alegeți dumneavoastră preferat limbaj de programare
  2. încărcați biblioteca de Matematică
  3. și pentru a găsi că Pi este definit deja acolo-gata de utilizare!

În cazul în care nu't au o bibliotecă Matematica la îndemână..

La MAI mod (mai mult o soluție universală) este:

uită-te în sus Pi pe Internet, de exemplu aici:

http://www.eveandersson.com/pi/digits/1000000 (1 milion de cifre .. ce's ta în virgulă mobilă de precizie? )

sau aici:

http://3.141592653589793238462643383279502884197169399375105820974944592.com/

sau aici:

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

L's foarte repede pentru a găsi cifrele de care aveți nevoie pentru orice precizie aritmetică doriți să utilizați, și, prin definirea unei constante, puteți asigurați-vă că don't deșeuri prețioase de timp de PROCESOR.

Nu numai ca aceasta este o parte plină de umor a răspuns, dar în realitate, dacă cineva ar merge mai departe și de a calcula valoarea de Pi într-o aplicație reală .. asta ar fi o mare pierdere de timp de PROCESOR, nu't-l? Cel puțin eu nu't vedea o aplicație reală pentru încercarea de a re-calcula acest lucru.

Stimate Moderator: vă rugăm să rețineți că OPERAȚIUNEA a întrebat: "cel mai Rapid Mod de a obține valoarea de PI"

 Tilo
Tilo
Răspuns editat 15 ianuarie 2019 в 6:31
42
0
 Tyler
Tyler
29 august 2008 в 9:22
2008-08-29T09:22:16+00:00
Mai mult
Sursă
Editează
#8406229

De BBP formula vă permite pentru a calcula n cifre in baza 2 (sau 16) - fără a fi nevoie să deranjez chiar cu anii n-1 cifre prima :)

27
0
Utilizator anonim
8 martie 2009 в 3:02
2009-03-08T03:02:12+00:00
Mai mult
Sursă
Editează
#8406237

În loc de a defini pi ca o constantă, eu folosesc întotdeauna acos(-1).

23
0
 krusty.ar
krusty.ar
12 ianuarie 2009 в 6:46
2009-01-12T18:46:22+00:00
Mai mult
Sursă
Editează
#8406234

Tocmai a dat peste una pe care ar trebui să fie aici pentru completare:

calcula PI în Piet

Ea are destul de frumos proprietatea că precizia poate fi îmbunătățită a face programul mai mare.

Aici's unele introspecție în limba în sine

22
0
Mark Cooper
Mark Cooper
6 ianuarie 2010 в 12:41
2010-01-06T12:41:03+00:00
Mai mult
Sursă
Editează
#8406242

Dacă acest articol este adevărat, atunci algoritm care Bellard s-au creat ar putea fi una dintre cele mai rapide disponibile. El a creat pi la 2,7 MILIARDE de cifre folosind un PC DESKTOP!

...și a publicat lui lucreze aici

Bună treabă Bellard, sunt pionier!

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

22
0
Andrea Ambu
Andrea Ambu
2 octombrie 2008 в 9:27
2008-10-02T21:27:55+00:00
Mai mult
Sursă
Editează
#8406232

Aceasta este o "clasic" metodă, foarte ușor să pună în aplicare. Această punere în aplicare, în python (nu asa de repede limba) e:

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)

Puteți găsi mai multe informații aici.

Oricum cel mai rapid mod de a obține o precizie cât mai-mult-ca-tine-vreau cu valoare de pi în python este:

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

aici este o bucată de sursă pentru gmpy pi metoda, eu nu't cred că codul este la fel de util ca un comentariu în acest caz:

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: am avut unele probleme cu cut și paste și identation, oricum puteți găsi sursa aici.

 phuclv
phuclv
Răspuns editat 31 ianuarie 2019 в 2:00
21
0
Michiel  de Mare
Michiel de Mare
6 august 2008 в 10:54
2008-08-06T22:54:12+00:00
Mai mult
Sursă
Editează
#8406227

Dacă prin cel mai rapid înseamnă mai rapid să tastați în codul, aici's golfscript soluție:

;''6666,-2%{2+.2/@*\/10.3??2*+}*`1000<~\;
20
0
 NihilistDandy
NihilistDandy
5 februarie 2011 в 5:26
2011-02-05T05:26:05+00:00
Mai mult
Sursă
Editează
#8406244

Utilizați Machin-ca formula

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.

Puse în aplicare în Sistem, de exemplu:

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

18
0
Daniel  C. Sobral
Daniel C. Sobral
17 septembrie 2009 в 4:30
2009-09-17T16:30:44+00:00
Mai mult
Sursă
Editează
#8406239

Dacă sunteți dispus să utilizeze o aproximare, 355 / 113 este bun pentru 6 cifre zecimale, și are avantajul de a fi ușor de utilizat, cu expresii întregi. Ca's nu la fel de important în aceste zile, ca "în virgulă mobilă matematica co-procesor" a încetat să mai aibă vreun sens, dar a fost destul de important o dată.

17
0
Utilizator anonim
26 februarie 2009 в 7:22
2009-02-26T19:22:22+00:00
Mai mult
Sursă
Editează
#8406236

Pi este exact 3! [Prof. Dr. Frink (The Simpsons)]

Glumă, dar aici's unul in C# (.NET Framework este necesar).

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;
        }
    }
}
 phuclv
phuclv
Răspuns editat 31 ianuarie 2019 в 1:59
16
0
 qwerty01
qwerty01
28 februarie 2010 в 3:52
2010-02-28T03:52:31+00:00
Mai mult
Sursă
Editează
#8406243

Cu duble:

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

Acest lucru va fi o acuratete de pana la 14 zecimale, suficient pentru a umple o cameră dublă (inexactitatea este, probabil, pentru că restul de zecimale în arc de cerc tangente sunt trunchiate).

De asemenea, Seth, l's 3.141592653589793238463, nu 64.

16
0
Brad Gilbert
Brad Gilbert
17 septembrie 2008 в 5:49
2008-09-17T17:49:15+00:00
Mai mult
Sursă
Editează
#8406231

Calcula PI la compilare-timp cu D.

( Copiate de pe 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
0
 JosephStyons
JosephStyons
12 ianuarie 2009 в 6:24
2009-01-12T18:24:48+00:00
Mai mult
Sursă
Editează
#8406233

Această versiune (în Delphi) nu este nimic special, dar este cel puțin mai repede decât versiunea Nick Hodge a postat pe blogul său :). Pe masina mea, este nevoie de aproximativ 16 secunde pentru a face un miliard de iterații, oferind o valoare de 3.1415926525879 (exacte parte este în bold).

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.
 phuclv
phuclv
Răspuns editat 31 ianuarie 2019 в 1:59
13
0
 Seth
Seth
22 decembrie 2009 в 9:13
2009-12-22T21:13:49+00:00
Mai mult
Sursă
Editează
#8406241

Dacă doriți să calcul o aproximare a valorii π (din anumite motive), ar trebui să încercați un binar de extracție algoritm. Bellard's îmbunătățirea BBP dă nu PI în O(N^2).


Dacă doriți să obține o apropiere de valoarea lui π de-a face calcule, atunci:

PI = 3.141592654

Acordate, care's doar o aproximare, și nu în întregime corecte. L's de un pic mai mult decât 0.00000000004102. (patru de zece trilionimi, despre 4/10,000,000,000).


Dacă vrei să faci matematica cu π, atunci ia-ti un creion și o hârtie sau un computer algebra pachet, și de a folosi π's valoare exactă, π.

Dacă vrei într-adevăr o formulă, aceasta este distractiv:

π = -i ln(-1)

12
0
Kristopher Johnson
Kristopher Johnson
20 februarie 2009 в 9:21
2009-02-20T21:21:20+00:00
Mai mult
Sursă
Editează
#8406235

Înapoi în zilele de demult, cu cuvântul de mici dimensiuni și lent sau inexistent de operațiuni în virgulă mobilă, am folosit pentru a face chestii de genul asta:

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

Pentru aplicații care nu't necesită o mulțime de precizie (jocuri video, de exemplu), acest lucru este foarte rapid și este suficient de precisă.

12
0
Adăugati o întrebare
Categorii
Toate
Tehnologii
Cultură
Viață / Artă
Stiință
Profesii
Afaceri
Utilizatori
Toate
Nou
Populare
1
Daniel Gogov
Înregistrat 6 zile în urmă
2
工藤 芳則
Înregistrat 1 săptămână în urmă
3
Ирина Беляева
Înregistrat 2 săptămâni în urmă
4
Darya Arsenyeva
Înregistrat 2 săptămâni în urmă
5
anyta nuam-nuam (LapuSiK)
Înregistrat 2 săptămâni în urmă
ID
JA
KO
RO
RU
ZH
© kzen.dev 2023
Sursă
stackoverflow.com
în cadrul licenței cc by-sa 3.0 cu atribuire