سؤال

أنا أبحث عن أسرع طريقة للحصول على قيمة π ، كما تحديا شخصيا.وبشكل أكثر تحديدا, أنا باستخدام الطرق التي لا تنطوي على استخدام #define الثوابت مثل M_PI, أو الثابت-ترميز عدد في.

البرنامج أدناه الاختبارات بطرق مختلفة أعلم.مضمنة إصدار التجميع في نظرية الخيار الأسرع ، لكن من الواضح أنه ليس المحمولة.لقد المدرجة كأساس لمقارنة ضد إصدارات أخرى.في بلدي التجارب ، مع المدمج الإضافية ، 4 * atan(1) الإصدار هو الأسرع على دول مجلس التعاون الخليجي 4.2, لأنه لصناعة السيارات في طيات 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;
}

و مضمنة الجمعية الاشياء (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-بت ضد 64 بت أيضا لأن تحسينات مختلفة) ، كما حاولت تحويل النظام من الاختبارات في جميع أنحاء.ولكن لا يزال ، atan2(0, -1) الإصدار لا يزال يخرج على رأس كل الوقت.

هل كانت مفيدة؟

المحلول

على طريقة مونت كارلو, كما ذكر ينطبق على بعض المفاهيم كبيرة ولكن من الواضح ليس الأسرع لا عن طريق تسديدة طويلة ، وليس من قبل أي قدر معقول.أيضا, كل هذا يتوقف على أي نوع من الدقة التي كنت تبحث عن.أسرع π أعرف من هو مع أرقام الثابت تلوينها.تبحث في Pi و Pi[PDF], هناك الكثير من الصيغ.

هنا هو الطريقة التي يتقاطع بسرعة — حوالي 14 رقما في التكرار. PiFast, الحالي أسرع تطبيق يستخدم هذه الصيغة مع الاتحاد الفرنسي للتنس.أنا فقط أكتب الصيغة ، لأن القانون واضح وصريح.هذه الصيغة تقريبا وجدت من قبل Ramanujan و اكتشافها من قبل Chudnovsky.هو في الواقع كيف تحسب عدة مليارات من أرقام من رقم — لذلك ليس من طريقة التجاهل.الصيغة سيتم تجاوز بسرعة و بما أننا تقسيم factorials ، سيكون من المفيد ثم إلى تأخير مثل هذه الحسابات إلى إزالة الشروط.

enter image description here

enter image description here

حيث ،

enter image description here

أدناه هو برنت Salamin الخوارزمية.ويكيبيديا يذكر أنه عندما a و ب هي "قريبة بما فيه الكفاية" ثم (a + b)2 / 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)

وأخيرا ماذا عن بعض pi الجولف (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);}

نصائح أخرى

أنا حقا أحب هذا البرنامج ، لأنه يقترب π من خلال النظر في منطقتها.

IOCCC 1988 : ويسلى.ج

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

هنا وصف عام تقنية لحساب بي أنني تعلمت في المدرسة الثانوية.

أنا فقط أشارك هذا لأنني أعتقد أنه هو بسيط بما فيه الكفاية أن أي شخص يمكن أن نتذكر أنه ، إلى أجل غير مسمى ، بالإضافة إلى أنه يعلمك مفهوم "مونتي كارلو" الأساليب-التي هي الأساليب الإحصائية التوصل إلى الإجابات التي لا تظهر على الفور أن تكون نتائجنا خلال العمليات العشوائية.

رسم مربع ، تدرج رباعي (ربع نصف دائرة) داخل مربع (رباعي مع دائرة نصف قطرها يساوي جانب من الساحة ، حتى يملأ قدر من مربع ممكن)

الآن رمي النبال في الساحة, و سجل فيها الأراضي -- وهذا هو اختيار نقطة عشوائية في أي مكان داخل مربع.بالطبع, هبطت داخل الساحة ، ولكن هل هو داخل نصف الدائرة ؟ سجل هذه الحقيقة.

كرر هذه العملية عدة مرات, و سوف تجد هناك نسبة من عدد من نقاط داخل نصف دائرة مقابل إجمالي عدد القيت ، الدعوة هذه النسبة x.

ومنذ منطقة ساحة r مرات r ، يمكن أن نستنتج أن منطقة شبه دائرة x مرات r مرات r (وهذا هو ، x مرات r تربيع).وبالتالي × 4 مرات سوف تعطيك بي.

هذه ليست طريقة سريعة للاستخدام.لكنه مثال جيد على طريقة مونت كارلو.و إذا كنت ننظر حولنا, قد تجد أن العديد من المشاكل وإلا خارج المهارات الحسابية يمكن حلها عن طريق هذه الأساليب.

في مصالح اكتمال C++ قالب الإصدار الذي الأمثل بناء ، حساب تقريبي من بي في وقت الترجمة ، وسوف مضمنة إلى قيمة واحدة.

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

ملاحظة I > 10, محسن يبني يمكن أن تكون بطيئة ، كذلك غير محسن يعمل.12 التكرار وأعتقد أن هناك حوالي 80 ألف يدعو إلى القيمة() (في غياب memoisation).

في الحقيقة هناك كتاب كامل مخصص (بين أمور أخرى) إلى سريع طرق حساب \pi:'Pi و الجمعية العمومية' ، جوناثان بيتر Borwein (متوفر على الأمازون).

درست الجمعية العمومية ذات الصلة خوارزميات قليلا جدا:انها مثيرة للاهتمام جدا (على الرغم من أن في بعض الأحيان غير تافهة).

علما بأن تنفيذ أحدث خوارزميات لحساب \pi, سوف تحتاج إلى multiprecision مكتبة الحسابية (GMP تماما خيار جيد ، على الرغم من انها كانت فترة من الوقت منذ آخر مرة استخدمته).

الوقت-التعقيد من أفضل الخوارزميات في O(M(n)log(n)) حيث M(n) هو الوقت التعقيد من أجل الضرب اثنين من n بت الاعداد الصحيحه (M(n)=O(n log(n) الدخول(log(n))) باستخدام FFT-بناء الخوارزميات التي عادة ما تكون هناك حاجة عند حساب أرقام \pi, و مثل هذه الخوارزمية يتم تنفيذها في GMP).

لاحظ أنه على الرغم من الرياضيات وراء خوارزميات قد لا تكون تافهة ، خوارزميات أنفسهم عادة بضعة أسطر من الزائفة رمز تنفيذها عادة ما تكون واضحة جدا (إذا اخترت عدم الكتابة الخاصة بك multiprecision الحساب :-) ).

الأجوبة التالية بالضبط كيفية القيام بذلك في أسرع طريقة ممكنة مع أقل الحوسبة الجهد.حتى إذا كنت لا ترغب في الإجابة ، يجب أن نعترف أنه في الواقع أسرع طريقة للحصول على قيمة PI.

على أسرع طريقة الحصول على قيمة Pi هو:

1) اختار لغة البرمجة المفضلة لديك 2) تحميل مكتبة الرياضيات 3) تجد أن Pi يعرف بالفعل هناك-جاهزة للاستخدام!

في حال لم يكن لديك مكتبة الرياضيات في متناول اليد..

على ثاني أسرع الطريقة (المزيد من الحل الشامل) هو:

ابحث بي على شبكة الإنترنت, على سبيل المثالهنا:

http://www.eveandersson.com/pi/digits/1000000 (1 مليون أرقام ..ما هي النقطة العائمة الدقة?)

أو هنا:

http://3.141592653589793238462643383279502884197169399375105820974944592.com/

أو هنا:

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

انها حقا سريعة للعثور على أرقام تحتاج لأي الدقة الحسابية كنت ترغب في استخدام وتعريف ثابت ، يمكنك التأكد من أن كنت لا نضيع الثمينة وقت وحدة المعالجة المركزية.

ليس هذا فقط هو جزئيا روح الدعابة الإجابة, ولكن في الواقع, إذا كان أي شخص سوف تمضي قدما وحساب قيمة Pi في تطبيق حقيقي ..التي من شأنها أن تكون كبيرة جدا النفايات من الوقت وحدة المعالجة المركزية ، أليس كذلك ؟ على الأقل أنا لا أرى تطبيق حقيقي لمحاولة إعادة حساب هذا.

عزيزي المشرف:يرجى ملاحظة أن المرجع سأل:"أسرع طريقة للحصول على قيمة PI"

على BBP الصيغة يسمح لك لحساب أقصى أرقام في قاعدة 2 (16) - دون الحاجة إلى عناء السابقة n-1 أرقام الأولى :)

بدلا من تحديد بي يكون ثابت, أنا دائما استخدام acos(-1).

فقط جئت عبر هذا واحد التي يجب أن تكون هنا للتأكد من اكتمالها:

حساب باي في بيت

فقد لطيف بدلا من ذلك الممتلكات التي دقة يمكن تحسين صنع البرنامج أكبر.

هنا's بعض التبصر في اللغة نفسها

إذا هذه المادة هو صحيح ، ثم الخوارزمية التي Bellard خلقت يمكن أن تكون واحدة من أسرع المتاحة.وقال انه قد خلق بي إلى 2.7 تريليون الأرقام باستخدام كمبيوتر سطح المكتب!

وقد نشرت له العمل هنا

عمل جيد Bellard, كنت رائدا!

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

هذا هو "الكلاسيكية" الأسلوب السهل جدا لتنفيذ.هذا التنفيذ ، في بيثون (ليس بهذه السرعة اللغة) كما يلي:

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)

يمكنك العثور على مزيد من المعلومات هنا.

على أي حال أسرع طريقة للحصول على الدقيق وكذلك الكثير كما تريد قيمة pi في بيثون هو:

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

هنا هو قطعة من مصدر gmpy باي طريقة, لا أعتقد رمز مفيدة بقدر التعليق في هذه الحالة:

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

تحرير: كان لي بعض المشاكل مع قص و لصق و identation, على أية حال يمكنك أن تجد المصدر هنا.

إذا أسرع تعني أسرع اكتب في المدونة هنا golfscript الحل:

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

استخدام ماشين مثل صيغة

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

إذا كنت على استعداد لاستخدام التقريب ، 355 / 113 هو جيد لمدة 6 أرقام عشرية ، لديه ميزة إضافية تتمثل في كونها قابلة للاستخدام مع عدد صحيح التعبيرات.ليس مهما هذه الأيام ، "النقطة العائمة الرياضيات co-المعالج" لم يعد لها أي معنى ، ولكن كان من المهم جدا مرة واحدة.

مع الزوجي:

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

هذا وسوف تكون دقيقة تصل إلى 14 المنازل العشرية ، ما يكفي لملء مزدوجة (عدم دقة هو الأرجح لأن بقية الكسور العشرية في قوس الظلال يتم اقتطاع).

أيضا سيث إنها 3.141592653589793238463, وليس 64.

حساب بي في وقت التحويل البرمجي مع D.

( نسخ من 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))) );

بي هو بالضبط 3![...التفاصيلفرينك (سمبسون)]

نكتة ، ولكن هنا واحد في 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;
        }
    }
}

هذا الإصدار (في دلفي) هو شيء خاص ، ولكن هو على الأقل أسرع من الإصدار نيك هودج نشرت على بلوق :).على الجهاز الخاص بي ، ويستغرق حوالي 16 ثانية للقيام مليار التكرار ، وإعطاء قيمة 3.1415926525879 (دقيق جزء في جريئة).

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.

مرة أخرى في الأيام الخوالي ، مع كلمة صغيرة الأحجام بطيئة أو معدومة عمليات النقطة العائمة, كنا نفعل مثل هذه الأشياء:

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

التطبيقات التي لا تتطلب الكثير من الدقة (ألعاب الفيديو ، على سبيل المثال) ، هذا هو سريع جدا و دقيقة بما فيه الكفاية.

إذا كنت ترغب في حساب تقريبي من قيمة π (لسبب ما) ، يجب أن تحاول الثنائية استخراج الخوارزمية. Bellard هو تحسين BBP يعطي يفعل بي في O(N^2).


إذا كنت ترغب في الحصول على تقريبي من قيمة π إلى القيام بعمليات حسابية ، ثم:

PI = 3.141592654

منح هذا فقط تقريبية و ليست دقيقة تماما.إنه قبل أكثر قليلا من 0.00000000004102.(أربعة عشر-تذكر, عن 4/10,000,000,000).


إذا كنت تريد أن تفعل الرياضيات مع π ، ثم الحصول على نفسك قلم رصاص و ورقة أو جهاز كمبيوتر الجبر الحزمة ، واستخدام π الدقيقة القيمة ، π.

إذا كنت تريد حقا صيغة هذا هو واحد متعة:

π = -أنا في(-1)

برنت طريقة نشر أعلاه من قبل كريس جيدة جدا ، برنت عموما هو عملاق في مجال التعسفي-الدقة الحسابية.

إذا كان كل ما تريده هو أقصى رقم الشهير BBP الصيغة مفيد في hex

حساب π من دائرة المساحة :-)

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

النهج الأفضل

للحصول على الإخراج القياسية الثوابت مثل pi أو مستوى المفاهيم يجب أن تذهب أولا مع builtins الطرق المتاحة اللغة التي تستخدمها.فإنه سيعود قيمة في أسرع طريقة و أفضل طريقة أيضا.أنا باستخدام بيثون للحصول على أسرع طريقة للحصول على قيمة pi

  • بي متغير من مكتبة الرياضيات.الرياضيات مكتبة تخزين المتغير pi المستمر.

math_pi.py

import math
print math.pi

تشغيل البرنامج النصي مع الوقت فائدة لينكس /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
  • استخدام القوس لأن طريقة الرياضيات

acos_pi.py

import math
print math.acos(-1)

تشغيل البرنامج النصي مع الوقت فائدة لينكس /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))

تشغيل البرنامج النصي مع الوقت فائدة لينكس /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 الطريقة التي قدمتها اللغة لأنها أسرع و أفضل للحصول على الإخراج.في بيثون استخدام الرياضيات.pi

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top