Ποιος είναι ο πιο γρήγορος τρόπος για να πάρετε την τιμή του π;

ψήφοι
275

Ψάχνω για το πιο γρήγορος τρόπος για να υπολογισθεί η τιμή του π, ως μια προσωπική πρόκληση. Πιο συγκεκριμένα, είμαι χρησιμοποιώντας τρόπους που δεν περιλαμβάνουν τη χρήση #defineσταθερών όπως M_PI, ή σκληρό-κωδικοποίηση του αριθμού in.

Το παρακάτω πρόγραμμα ελέγχει τους διάφορους τρόπους ξέρω. Η έκδοση συγκρότημα inline δεν είναι, θεωρητικά, η ταχύτερη επιλογή, αν και σαφώς φορητό. Το έχω συμπεριληφθεί ως βασική γραμμή για να συγκρίνει με τις άλλες εκδόσεις. Στις δοκιμές μου, με εντοιχισμένη ντουλάπα, η 4 * atan(1)έκδοση είναι ταχύτερη σε GCC 4.2, επειδή auto-διπλώνει το atan(1)σε ένα σταθερό. Με -fno-builtinδιευκρινίζεται, η atan2(0, -1)έκδοση είναι ταχύτερη.

Εδώ είναι το κύριο πρόγραμμα δοκιμών ( pitimes.c):

#include <math.h>
#include <stdio.h>
#include <time.h>

#define ITERS 10000000
#define TESTWITH(x) {                                                       \
    diff = 0.0;                                                             \
    time1 = clock();                                                        \
    for (i = 0; i < ITERS; ++i)                                             \
        diff += (x) - M_PI;                                                 \
    time2 = clock();                                                        \
    printf(%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;
}

Και τα πράγματα συγκρότημα inline ( fldpi.c) που θα λειτουργήσει μόνο για συστήματα x86 και x64:

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

Και μια κατασκευή σενάριο που βασίζεται όλες τις διαμορφώσεις είμαι δοκιμή ( build.sh):

#!/bin/sh
gcc -O3 -Wall -c           -m32 -o fldpi-32.o fldpi.c
gcc -O3 -Wall -c           -m64 -o fldpi-64.o fldpi.c

gcc -O3 -Wall -ffast-math  -m32 -o pitimes1-32 pitimes.c fldpi-32.o
gcc -O3 -Wall              -m32 -o pitimes2-32 pitimes.c fldpi-32.o -lm
gcc -O3 -Wall -fno-builtin -m32 -o pitimes3-32 pitimes.c fldpi-32.o -lm
gcc -O3 -Wall -ffast-math  -m64 -o pitimes1-64 pitimes.c fldpi-64.o -lm
gcc -O3 -Wall              -m64 -o pitimes2-64 pitimes.c fldpi-64.o -lm
gcc -O3 -Wall -fno-builtin -m64 -o pitimes3-64 pitimes.c fldpi-64.o -lm

Εκτός από τη δοκιμή μεταξύ των διαφόρων σημαιών μεταγλωττιστή (έχω σύγκριση 32-bit έναντι 64-bit πάρα πολύ, επειδή οι βελτιστοποιήσεις είναι διαφορετικές), έχω επίσης δοκιμάσει να αντιστραφεί η σειρά των δοκιμών γύρω. Αλλά και πάλι, η atan2(0, -1)έκδοση εξακολουθεί να βγαίνει στην κορυφή κάθε φορά.

Δημοσιεύθηκε 01/08/2008 στις 06:21
πηγή χρήστη
Σε άλλες γλώσσες...                            


23 απαντήσεις

ψήφοι
180

Η μέθοδος Monte Carlo , όπως αναφέρθηκε, εφαρμόζεται μερικές μεγάλες ιδέες, αλλά είναι, προφανώς, δεν την ταχύτερη, όχι κατά διάνοια, όχι από κάθε εύλογο μέτρο. Επίσης, όλα εξαρτώνται από το είδος της ακρίβειας που ψάχνετε. Ο πιο γρήγορος π γνωρίζω είναι το ένα με τα ψηφία σκληρό κωδικοποιημένες. Κοιτάζοντας Pi και π [PDF] , υπάρχουν πολλοί τύποι.

Εδώ είναι μια μέθοδος που συγκλίνει γρήγορα - περίπου 14 ψηφία ανά επανάληψη. PiFast , η τρέχουσα ταχύτερη εφαρμογή, χρησιμοποιεί αυτόν τον τύπο με το FFT . Θα γράψω μόνο τον τύπο, δεδομένου ότι ο κώδικας είναι απλή. Αυτός ο τύπος ήταν σχεδόν βρέθηκε από Ramanujan και ανακαλύφθηκε από Τσουντνόφσκι . Είναι πραγματικά πώς υπολογίζεται πολλά δισεκατομμύρια ψηφία του αριθμού - έτσι δεν είναι μια μέθοδος για να αγνοήσει. Ο τύπος θα ξεχειλίσει γρήγορα και, δεδομένου ότι τα διαιρούμενα factorials, θα ήταν επωφελές στη συνέχεια να καθυστερήσει αυτών των υπολογισμών για την απομάκρυνση όρους.

εισάγετε περιγραφή της εικόνας εδώ

εισάγετε περιγραφή της εικόνας εδώ

όπου,

εισάγετε περιγραφή της εικόνας εδώ

Παρακάτω είναι ο αλγόριθμος Brent-Salamin . Wikipedia αναφέρει ότι όταν ένα και β είναι «αρκετά κοντά», τότε (α + β) ² / 4t θα είναι μια προσέγγιση του π. Δεν είμαι σίγουρος τι «αρκετά κοντά» μέσα, αλλά από τις δοκιμές μου, μια επανάληψη πήρε 2 ψηφία, δύο πήρε 7, και τρεις είχαν 15, φυσικά, αυτό είναι με διπλά, οπότε θα μπορούσε να σφάλμα με βάση την εκπροσώπηση της και η αλήθεια υπολογισμός θα μπορούσε να είναι πιο ακριβείς.

let pi_2 iters =
    let rec loop_ a b t p i =
        if i = 0 then a,b,t,p
        else
            let a_n = (a +. b) /. 2.0 
            and b_n = sqrt (a*.b)
            and p_n = 2.0 *. p in
            let t_n = t -. (p *. (a -. a_n) *. (a -. a_n)) in
            loop_ a_n b_n t_n p_n (i - 1)
    in 
    let a,b,t,p = loop_ (1.0) (1.0 /. (sqrt 2.0)) (1.0/.4.0) (1.0) iters in
    (a +. b) *. (a +. b) /. (4.0 *. t)

Τέλος, πώς για κάποια π γκολφ (800 ψηφία); 160 χαρακτήρες!

int a=10000,b,c=2800,d,e,f[2801],g;main(){for(;b-c;)f[b++]=a/5;for(;d=0,g=c*2;c-=14,printf("%.4d",e+d/a),e=d%a)for(b=c;d+=f[b]*a,f[b]=d%--g,d/=g--,--b;d*=b);}
Απαντήθηκε 02/08/2008 στις 19:22
πηγή χρήστη

ψήφοι
96

Μου αρέσει πολύ αυτό το πρόγραμμα, το οποίο προσεγγίζει π κοιτάζοντας δικό της χώρο :-)

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()
{
            _-_-_-_
       _-_-_-_-_-_-_-_-_
    _-_-_-_-_-_-_-_-_-_-_-_
  _-_-_-_-_-_-_-_-_-_-_-_-_-_
 _-_-_-_-_-_-_-_-_-_-_-_-_-_-_
 _-_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
 _-_-_-_-_-_-_-_-_-_-_-_-_-_-_
 _-_-_-_-_-_-_-_-_-_-_-_-_-_-_
  _-_-_-_-_-_-_-_-_-_-_-_-_-_
    _-_-_-_-_-_-_-_-_-_-_-_
        _-_-_-_-_-_-_-_
            _-_-_-_
}
Απαντήθηκε 02/09/2008 στις 14:28
πηγή χρήστη

ψήφοι
72

Εδώ είναι μια γενική περιγραφή της τεχνικής για τον υπολογισμό pi που έμαθα στο γυμνάσιο.

Συμμερίζομαι μόνο αυτό, διότι πιστεύω ότι είναι αρκετά απλό που ο καθένας μπορεί να θυμηθεί, επ 'αόριστον, καθώς σας διδάσκει την έννοια των μεθόδων «Μόντε Κάρλο» - που είναι στατιστικών μεθόδων που φθάνουν σε απαντήσεις που δεν εμφανίζονται αμέσως να συνάγονται μέσα από τυχαίες διαδικασίες.

Σχεδιάστε ένα τετράγωνο, και εγγράψει τεταρτημόριο (ένα τέταρτο ενός ημι-κύκλο) μέσα σε αυτό το τετράγωνο (ένα τεταρτημόριο με ακτίνα ίση με την πλευρά του τετραγώνου, έτσι ώστε να γεμίζει τόσο της πλατείας του δυνατού)

Τώρα ρίξει ένα βέλος στην πλατεία, και να καταγράφει όταν προσγειώνεται - δηλαδή, να επιλέξει ένα τυχαίο σημείο οπουδήποτε μέσα στο τετράγωνο. Φυσικά, προσγειώθηκε μέσα στο τετράγωνο, αλλά είναι μέσα στο ημικύκλιο; Καταγράψτε το γεγονός αυτό.

Επαναλάβετε αυτή τη διαδικασία πολλές φορές - και θα διαπιστώσετε ότι υπάρχει μια αναλογία του αριθμού των σημείων στο εσωτερικό του ημικυκλίου σε σχέση με το συνολικό αριθμό ρίχνονται, καλέστε αυτό το λόγο x.

Δεδομένου ότι η περιοχή της πλατείας είναι φορές r r, μπορείτε να συμπεράνετε ότι η περιοχή του ημι κύκλο είναι φορές x r φορές r (δηλαδή, φορές x r τετράγωνο). Ως εκ τούτου x φορές 4 θα σας δώσει πίν.

Αυτό δεν είναι μια γρήγορη μέθοδος για να χρησιμοποιήσετε. Αλλά είναι ένα ωραίο παράδειγμα μιας μεθόδου Monte Carlo. Και αν κοιτάξουμε γύρω μας, μπορείτε να διαπιστώσετε ότι πολλά προβλήματα με άλλο τρόπο εκτός της υπολογιστικής ικανότητές σας μπορεί να λυθεί με τέτοιες μεθόδους.

Απαντήθηκε 01/08/2008 στις 14:37
πηγή χρήστη

ψήφοι
51

Για λόγους πληρότητας, η C ++ έκδοση πρότυπο, το οποίο για μια βελτιστοποιημένη κατασκευή θα υπολογίσει PI κατά τη μεταγλώττιση και θα inline σε μια ενιαία τιμή.

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

Σημείωση για Ι> 10, βελτιστοποιημένη χτίζει μπορεί να είναι αργή, το ίδιο και για μη-βελτιστοποιημένη τρεξίματα. Για 12 επαναλήψεις πιστεύω ότι υπάρχουν περίπου 80 χιλ κλήσεις προς τιμή () (απουσία memoisation).

Απαντήθηκε 22/12/2009 στις 16:40
πηγή χρήστη

ψήφοι
40

Υπάρχει πράγματι ένα ολόκληρο βιβλίο αφιερωμένο (μεταξύ άλλων) για γρήγορη μεθόδους για τον υπολογισμό του \ pi: «Pi και η Γενική Συνέλευση», από τον Jonathan και ο Peter Borwein ( διαθέσιμο στο Amazon ).

Σπούδασα στην Ετήσια Γενική Συνέλευση και των σχετικών αλγορίθμων αρκετά: είναι πολύ ενδιαφέρον (αν και μερικές φορές μη-τετριμμένες).

Να σημειωθεί ότι για την εφαρμογή πιο σύγχρονες αλγόριθμους για να υπολογίσει \ pi, θα χρειαστείτε μια αριθμητική πολλαπλής ακριβείας βιβλιοθήκη ( GMP είναι αρκετά καλή επιλογή, αν και έχει περάσει καιρός από τότε που το χρησιμοποιούσαν τελευταία).

Ο χρόνος-πολυπλοκότητα των καλύτερων αλγορίθμων είναι O (Μ (n) log (n)), όπου το Μ (n) είναι ο χρόνος-πολυπλοκότητας για τον πολλαπλασιασμό των δύο ακέραιοι n-bit (Μ (n) = O (n log (n) log (log (n))) χρησιμοποιώντας αλγόριθμους FFT-based, τα οποία συνήθως απαιτούνται κατά τον υπολογισμό ψηφία του \ pi, και ένας τέτοιος αλγόριθμος υλοποιείται σε GMP).

Σημειώστε ότι ακόμη και αν οι μαθηματικά πίσω από τους αλγόριθμους μπορεί να μην είναι ασήμαντο, οι ίδιοι οι αλγόριθμοι είναι συνήθως μερικές γραμμές του ψευδο-κώδικα, και η εφαρμογή τους είναι συνήθως πολύ απλή (αν δεν επέλεξε να γράψετε τη δική σας αριθμητική multiprecision :-)).

Απαντήθηκε 24/08/2008 στις 18:14
πηγή χρήστη

ψήφοι
36

Οι παρακάτω απαντήσεις ακριβώς πώς να το κάνουμε αυτό με τον ταχύτερο δυνατό τρόπο - με την ελάχιστη υπολογιστική προσπάθεια . Ακόμα κι αν δεν σας αρέσει η απάντηση, θα πρέπει να παραδεχτούμε ότι είναι πράγματι ο πιο γρήγορος τρόπος για να πάρετε την τιμή του PI.

Ο πιο γρήγορος τρόπος για να πάρετε την τιμή του π είναι:

  1. επέλεξε την αγαπημένη σας γλώσσα προγραμματισμού
  2. φορτίο αυτό της βιβλιοθήκης Μαθηματικά
  3. και διαπιστώνουν ότι Pi έχει ήδη καθοριστεί εκεί !! έτοιμο για να το χρησιμοποιήσετε ..

στην περίπτωση που δεν έχουν βιβλιοθήκη μαθηματικών στο χέρι ..

ο δεύτερος ταχύτερος τρόπος (πάνω καθολική λύση) είναι:

αναζητήσετε Pi στο Διαδίκτυο, π.χ. εδώ:

http://www.eveandersson.com/pi/digits/1000000 (1 εκατομμύριο ψηφία .. αυτό είναι κυμαινόμενο ακρίβεια το σημείο σας;)

ή εδώ:

http://3.141592653589793238462643383279502884197169399375105820974944592.com/

ή εδώ:

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

Είναι πραγματικά γρήγορα για να βρουν τα ψηφία που χρειάζεστε για ό, τι ακρίβειας αριθμητική θέλετε να χρησιμοποιήσετε, και ορίζοντας ένα σταθερό, μπορείτε να είστε σίγουροι ότι δεν θα χάσουμε πολύτιμο χρόνο της CPU.

Δεν είναι μόνο αυτό μια εν μέρει χιουμοριστική απάντηση, αλλά στην πραγματικότητα, αν κάποιος θα προχωρήσει και υπολογίζουμε την τιμή του π σε μια πραγματική εφαρμογή .. ότι θα ήταν ένα πολύ μεγάλο χάσιμο χρόνου της CPU, έτσι δεν είναι; Τουλάχιστον εγώ δεν βλέπω μια πραγματική αίτηση για την προσπάθεια να αποκαταστήσει τον υπολογισμό αυτό.

Αγαπητοί Συντονιστής: παρακαλώ σημειώστε ότι το ΕΠ ρώτησε: «γρηγορότερος τρόπος για να πάρετε την τιμή του PI»

Απαντήθηκε 28/10/2011 στις 02:02
πηγή χρήστη

ψήφοι
25

Η φόρμουλα BBP επιτρέπει να υπολογίσουμε την νιοστή ψηφίο - στη βάση 2 (ή 16) - χωρίς να χρειάζεται να ενοχλεί ακόμα και με τις προηγούμενες n 1-ψηφία πρώτο :)

Απαντήθηκε 29/08/2008 στις 10:22
πηγή χρήστη

ψήφοι
21

Αντί του καθορισμού π ως μια σταθερή, χρησιμοποιώ πάντα acos(-1).

Απαντήθηκε 08/03/2009 στις 04:02
πηγή χρήστη

ψήφοι
20

Εάν αυτό το άρθρο είναι αλήθεια, τότε ο αλγόριθμος που Bellard έχει δημιουργήσει μπορούσε να είναι ένα από τα ταχύτερη διαθέσιμη. Έχει δημιουργήσει pi με 2,7 τρισεκ ψηφία, χρησιμοποιώντας έναν επιτραπέζιο υπολογιστή!

... και έχει δημοσιεύσει του έργου εδώ

Καλή δουλειά Bellard, είσαι πρωτοπόρος!

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

Απαντήθηκε 06/01/2010 στις 13:41
πηγή χρήστη

ψήφοι
20

Απλά ήρθε σε ένα αυτό που θα έπρεπε να είναι εδώ για λόγους πληρότητας:

υπολογίζουν PI στο Piet

Έχει την μάλλον συμπαθητική ιδιότητα ότι η ακρίβεια μπορεί να βελτιωθεί καθιστώντας το πρόγραμμα μεγαλύτερα.

Εδώ «s κάποια εικόνα για την ίδια τη γλώσσα

Απαντήθηκε 12/01/2009 στις 19:46
πηγή χρήστη

ψήφοι
19

Αυτό είναι ένα «κλασικό» τρόπο, είναι πολύ εύκολο να εφαρμοστούν. Αυτή η εφαρμογή, σε python (όχι τόσο γρήγορα γλώσσα) κάνει:

from math import pi
from time import time


precision = 10**6 # higher value -> higher precision
                  # lower  value -> higher speed

t = time()

calc = 0
for k in xrange(0, precision):
    calc += ((-1)**k) / (2*k+1.)
calc *= 4. # this is just a little optimization

t = time()-t

print "Calculated: %.40f" % calc
print "Costant pi: %.40f" % pi
print "Difference: %.40f" % abs(calc-pi)
print "Time elapsed: %s" % repr(t)

Μπορείτε να βρείτε περισσότερες πληροφορίες εδώ .

Τέλος πάντων ο πιο γρήγορος τρόπος για να πάρετε μια ακριβή και-πολύ-as-you-θέλουν τιμή του π σε python είναι:

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

εδώ είναι το κομμάτι του κώδικα για τη μέθοδο gmpy pi, δεν νομίζω ότι ο κώδικας είναι τόσο χρήσιμο όσο το σχόλιο σε αυτή την περίπτωση:

static char doc_pi[]="\
pi(n): returns pi with n bits of precision in an mpf object\n\
";

/* This function was originally from netlib, package bmp, by
 * Richard P. Brent. Paulo Cesar Pereira de Andrade converted
 * it to C and used it in his LISP interpreter.
 *
 * Original comments:
 * 
 *   sets mp pi = 3.14159... to the available precision.
 *   uses the gauss-legendre algorithm.
 *   this method requires time o(ln(t)m(t)), so it is slower
 *   than mppi if m(t) = o(t**2), but would be faster for
 *   large t if a faster multiplication algorithm were used
 *   (see comments in mpmul).
 *   for a description of the method, see - multiple-precision
 *   zero-finding and the complexity of elementary function
 *   evaluation (by r. p. brent), in analytic computational
 *   complexity (edited by j. f. traub), academic press, 1976, 151-176.
 *   rounding options not implemented, no guard digits used.
*/
static PyObject *
Pygmpy_pi(PyObject *self, PyObject *args)
{
    PympfObject *pi;
    int precision;
    mpf_t r_i2, r_i3, r_i4;
    mpf_t ix;

    ONE_ARG("pi", "i", &precision);
    if(!(pi = Pympf_new(precision))) {
        return NULL;
    }

    mpf_set_si(pi->f, 1);

    mpf_init(ix);
    mpf_set_ui(ix, 1);

    mpf_init2(r_i2, precision);

    mpf_init2(r_i3, precision);
    mpf_set_d(r_i3, 0.25);

    mpf_init2(r_i4, precision);
    mpf_set_d(r_i4, 0.5);
    mpf_sqrt(r_i4, r_i4);

    for (;;) {
        mpf_set(r_i2, pi->f);
        mpf_add(pi->f, pi->f, r_i4);
        mpf_div_ui(pi->f, pi->f, 2);
        mpf_mul(r_i4, r_i2, r_i4);
        mpf_sub(r_i2, pi->f, r_i2);
        mpf_mul(r_i2, r_i2, r_i2);
        mpf_mul(r_i2, r_i2, ix);
        mpf_sub(r_i3, r_i3, r_i2);
        mpf_sqrt(r_i4, r_i4);
        mpf_mul_ui(ix, ix, 2);
        /* Check for convergence */
        if (!(mpf_cmp_si(r_i2, 0) && 
              mpf_get_prec(r_i2) >= (unsigned)precision)) {
            mpf_mul(pi->f, pi->f, r_i4);
            mpf_div(pi->f, pi->f, r_i3);
            break;
        }
    }

    mpf_clear(ix);
    mpf_clear(r_i2);
    mpf_clear(r_i3);
    mpf_clear(r_i4);

    return (PyObject*)pi;
}

EDIT: Είχα κάποιο πρόβλημα με αποκοπή και επικόλληση και identation, ούτως ή άλλως μπορείτε να βρείτε την πηγή εδώ .

Απαντήθηκε 02/10/2008 στις 22:27
πηγή χρήστη

ψήφοι
17

Αν η ταχύτερη που σημαίνει ταχύτερη να πληκτρολογήσετε τον κωδικό, εδώ είναι το golfscript λύση:

;''6666,-2%{2+.2/@*\/10.3??2*+}*`1000<~\;
Απαντήθηκε 06/08/2008 στις 23:54
πηγή χρήστη

ψήφοι
15

Χρησιμοποιήστε το 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.

Υλοποιήθηκε στο σχήμα, για παράδειγμα:

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

Απαντήθηκε 05/02/2011 στις 06:26
πηγή χρήστη

ψήφοι
15

Με διπλό:

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

Αυτό θα είναι ακριβείς μέχρι 14 δεκαδικά ψηφία, αρκετή για να καλύψει ένα διπλό (η ανακρίβεια είναι πιθανώς επειδή το υπόλοιπο των δεκαδικών ψηφίων στις εφαπτόμενες τόξου περικόπτονται).

Επίσης Seth, είναι 3,14159265358979323846 3 , όχι 64.

Απαντήθηκε 28/02/2010 στις 04:52
πηγή χρήστη

ψήφοι
15

Εάν είστε πρόθυμοι να χρησιμοποιήσουν μια προσέγγιση, 355 / 113είναι καλό για 6 δεκαδικά ψηφία, και έχει το πρόσθετο πλεονέκτημα ότι μπορεί να χρησιμοποιηθεί με ακέραιες εκφράσεις. Αυτό δεν είναι τόσο σημαντικό αυτές τις μέρες, ως «πλωτό σημείο μαθηματικά συν-επεξεργαστής» έπαψε να έχει κάποιο νόημα, αλλά ήταν πολύ σημαντικό μια φορά.

Απαντήθηκε 17/09/2009 στις 17:30
πηγή χρήστη

ψήφοι
15

Pi είναι ακριβώς 3! [Καθηγητής Frink (Simpsons)]

Αστείο, αλλά εδώ είναι ένα σε C # (.NET-Framework απαιτείται).

using System;
using System.Text;

class Program {
    static void Main(string[] args) {
        int Digits = 100;

        BigNumber x = new BigNumber(Digits);
        BigNumber y = new BigNumber(Digits);
        x.ArcTan(16, 5);
        y.ArcTan(4, 239);
        x.Subtract(y);
        string pi = x.ToString();
        Console.WriteLine(pi);
    }
}

public class BigNumber {
    private UInt32[] number;
    private int size;
    private int maxDigits;

    public BigNumber(int maxDigits) {
        this.maxDigits = maxDigits;
        this.size = (int)Math.Ceiling((float)maxDigits * 0.104) + 2;
        number = new UInt32[size];
    }
    public BigNumber(int maxDigits, UInt32 intPart)
        : this(maxDigits) {
        number[0] = intPart;
        for (int i = 1; i < size; i++) {
            number[i] = 0;
        }
    }
    private void VerifySameSize(BigNumber value) {
        if (Object.ReferenceEquals(this, value))
            throw new Exception("BigNumbers cannot operate on themselves");
        if (value.size != this.size)
            throw new Exception("BigNumbers must have the same size");
    }

    public void Add(BigNumber value) {
        VerifySameSize(value);

        int index = size - 1;
        while (index >= 0 && value.number[index] == 0)
            index--;

        UInt32 carry = 0;
        while (index >= 0) {
            UInt64 result = (UInt64)number[index] +
                            value.number[index] + carry;
            number[index] = (UInt32)result;
            if (result >= 0x100000000U)
                carry = 1;
            else
                carry = 0;
            index--;
        }
    }
    public void Subtract(BigNumber value) {
        VerifySameSize(value);

        int index = size - 1;
        while (index >= 0 && value.number[index] == 0)
            index--;

        UInt32 borrow = 0;
        while (index >= 0) {
            UInt64 result = 0x100000000U + (UInt64)number[index] -
                            value.number[index] - borrow;
            number[index] = (UInt32)result;
            if (result >= 0x100000000U)
                borrow = 0;
            else
                borrow = 1;
            index--;
        }
    }
    public void Multiply(UInt32 value) {
        int index = size - 1;
        while (index >= 0 && number[index] == 0)
            index--;

        UInt32 carry = 0;
        while (index >= 0) {
            UInt64 result = (UInt64)number[index] * value + carry;
            number[index] = (UInt32)result;
            carry = (UInt32)(result >> 32);
            index--;
        }
    }
    public void Divide(UInt32 value) {
        int index = 0;
        while (index < size && number[index] == 0)
            index++;

        UInt32 carry = 0;
        while (index < size) {
            UInt64 result = number[index] + ((UInt64)carry << 32);
            number[index] = (UInt32)(result / (UInt64)value);
            carry = (UInt32)(result % (UInt64)value);
            index++;
        }
    }
    public void Assign(BigNumber value) {
        VerifySameSize(value);
        for (int i = 0; i < size; i++) {
            number[i] = value.number[i];
        }
    }

    public override string ToString() {
        BigNumber temp = new BigNumber(maxDigits);
        temp.Assign(this);

        StringBuilder sb = new StringBuilder();
        sb.Append(temp.number[0]);
        sb.Append(System.Globalization.CultureInfo.CurrentCulture.NumberFormat.CurrencyDecimalSeparator);

        int digitCount = 0;
        while (digitCount < maxDigits) {
            temp.number[0] = 0;
            temp.Multiply(100000);
            sb.AppendFormat("{0:D5}", temp.number[0]);
            digitCount += 5;
        }

        return sb.ToString();
    }
    public bool IsZero() {
        foreach (UInt32 item in number) {
            if (item != 0)
                return false;
        }
        return true;
    }

    public void ArcTan(UInt32 multiplicand, UInt32 reciprocal) {
        BigNumber X = new BigNumber(maxDigits, multiplicand);
        X.Divide(reciprocal);
        reciprocal *= reciprocal;

        this.Assign(X);

        BigNumber term = new BigNumber(maxDigits);
        UInt32 divisor = 1;
        bool subtractTerm = true;
        while (true) {
            X.Divide(reciprocal);
            term.Assign(X);
            divisor += 2;
            term.Divide(divisor);
            if (term.IsZero())
                break;

            if (subtractTerm)
                this.Subtract(term);
            else
                this.Add(term);
            subtractTerm = !subtractTerm;
        }
    }
}
Απαντήθηκε 26/02/2009 στις 20:22
πηγή χρήστη

ψήφοι
15

Υπολογίστε PI κατά τη μεταγλώττιση χρόνο με Δ

(Αντιγραφή από 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))) );
Απαντήθηκε 17/09/2008 στις 18:49
πηγή χρήστη

ψήφοι
13

Αυτή η έκδοση (στους Δελφούς) είναι τίποτα το ιδιαίτερο, αλλά είναι τουλάχιστον πιο γρήγορα από την έκδοση Nick Hodge δημοσίευσε στο blog του :). Την μηχανή μου, χρειάζεται περίπου 16 δευτερόλεπτα για να κάνει ένα δισεκατομμύριο επαναλήψεις, δίνοντας μια αξία 3,14159265 25.879 (το ακριβές μέρος είναι με έντονα γράμματα).

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.
Απαντήθηκε 12/01/2009 στις 19:24
πηγή χρήστη

ψήφοι
12

Αν θέλετε να υπολογίσετε κατά προσέγγιση την αξία του π (για κάποιο λόγο), θα πρέπει να δοκιμάσετε ένα δυαδικό αλγόριθμο εξόρυξης. Bellard της βελτίωσης της BBP δίνει κάνει PI σε O (Ν ^ 2).


Αν θέλετε να αποκτήσετε μια προσέγγιση της αξίας των π για να κάνει υπολογισμούς, τότε:

PI = 3.141592654

Σύμφωνοι, αυτό είναι μόνο μια προσέγγιση, και δεν είναι απολύτως ακριβή. Είναι μακριά από λίγο περισσότερο από 0,00000000004102. (τεσσάρων δέκα-trillionths, περίπου 4 / 10000000000 ).


Αν θέλετε να κάνετε τα μαθηματικά με π, στη συνέχεια να πάρει τον εαυτό σας ένα μολύβι και χαρτί ή ένα πακέτο άλγεβρα υπολογιστή, και να χρησιμοποιήσετε ακριβή τιμή π, το π.

Αν θέλετε πραγματικά έναν τύπο, αυτό είναι διασκεδαστικό:

π = - i ln (-1)

Απαντήθηκε 22/12/2009 στις 22:13
πηγή χρήστη

ψήφοι
12

Επιστροφή στις παλιές μέρες, με μικρά μεγέθη λέξη και τις πράξεις αργή ή ανύπαρκτη floating-point, χρησιμοποιήσαμε για να κάνουμε τα πράγματα όπως αυτό:

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

Για τις εφαρμογές που δεν απαιτούν πολλή ακρίβεια (video games, για παράδειγμα), αυτό είναι πολύ γρήγορη και είναι αρκετά ακριβείς.

Απαντήθηκε 20/02/2009 στις 22:21
πηγή χρήστη

ψήφοι
11

μέθοδος Brent που δημοσιεύτηκε πάνω από τον Chris είναι πολύ καλή? Brent γενικά είναι ένας γίγαντας στον τομέα της αριθμητικής αυθαίρετης ακρίβειας.

Αν το μόνο που θέλετε είναι το νιοστό ψηφίο, ο διάσημος τύπος BBP είναι χρήσιμη σε εξάγωνο

Απαντήθηκε 04/08/2009 στις 22:39
πηγή χρήστη

ψήφοι
1

Υπολογισμός π από την περιοχή κύκλο :-)

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

Απαντήθηκε 03/06/2017 στις 17:13
πηγή χρήστη

ψήφοι
0

καλύτερη προσέγγιση

Για να πάρετε την έξοδο τυπικών σταθερές, όπως π ή των τυποποιημένων εννοιών, θα πρέπει πρώτα να πάτε με τις μεθόδους builtins διαθέσιμη η γλώσσα που χρησιμοποιείτε. Θα επιστρέψει την αξία με τον πιο γρήγορο τρόπο και καλύτερος τρόπος επίσης. Είμαι με τη χρήση python για να πάρει την πιο γρήγορος τρόπος για να πάρετε το pi αξία

  • pi μεταβλητή της βιβλιοθήκης μαθηματικών . Βιβλιοθήκη Math αποθηκεύσει η μεταβλητή pi ως σταθερά.

math_pi.py

import math
print math.pi

Εκτελέστε το σενάριο με το χρόνο χρησιμότητα του linux /usr/bin/time -v python math_pi.py

Παραγωγή:

Command being timed: "python math_pi.py"
User time (seconds): 0.01
System time (seconds): 0.01
Percent of CPU this job got: 91%
Elapsed (wall clock) time (h:mm:ss or m:ss): 0:00.03
  • Χρησιμοποιήστε το τόξο cos μέθοδο των μαθηματικών

acos_pi.py

import math
print math.acos(-1)

Εκτελέστε το σενάριο με το χρόνο χρησιμότητα του linux /usr/bin/time -v python acos_pi.py

Παραγωγή:

Command being timed: "python acos_pi.py"
User time (seconds): 0.02
System time (seconds): 0.01
Percent of CPU this job got: 94%
Elapsed (wall clock) time (h:mm:ss or m:ss): 0:00.03

bbp_pi.py

from decimal import Decimal, getcontext
getcontext().prec=100
print sum(1/Decimal(16)**k * 
          (Decimal(4)/(8*k+1) - 
           Decimal(2)/(8*k+4) - 
           Decimal(1)/(8*k+5) -
           Decimal(1)/(8*k+6)) for k in range(100))

Εκτελέστε το σενάριο με το χρόνο χρησιμότητα του linux /usr/bin/time -v python bbp_pi.py

Παραγωγή:

Command being timed: "python c.py"
User time (seconds): 0.05
System time (seconds): 0.01
Percent of CPU this job got: 98%
Elapsed (wall clock) time (h:mm:ss or m:ss): 0:00.06

Έτσι καλύτερος τρόπος είναι να χρησιμοποιήσετε builtins μέθοδο που προβλέπεται από τη γλώσσα αιτία είναι η ταχύτερη και καλύτερη για να πάρει το αποτέλεσμα. Σε python χρήση math.pi

Απαντήθηκε 18/06/2018 στις 10:07
πηγή χρήστη

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