tt değerini almanın en hızlı yolu nedir?

oy
275

Kişisel bir meydan okuma olarak, tt değerini elde etmek için en hızlı yol arıyorum. Daha spesifik olarak, ben kullanarak içermeyen yollar kullanıyorum #definegibi sabitleri M_PIveya numarayı sabit kodlamak.

Program aşağıda bildiğim çeşitli yollarını test eder. Satır içi montaj versiyonu olsa açıkça, teorik olarak, taşınabilir en hızlı seçenek değildir. Ben diğer sürümleri karşı karşılaştırmak için temel olarak dahil ettik. Benim testlerde, yerleşik ins ile, 4 * atan(1)o otomatik katlanabilir çünkü sürümü, GCC 4.2 üzerinde en hızlı atan(1)bir sabit içine. Ile -fno-builtinbelirtilen, atan2(0, -1)sürüm en hızlı.

İşte ana test programı (var 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;
}

Ve satır içi montaj şeyler ( fldpi.csadece x86 ve x64 sistemleri için çalışacaktır):

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

Ve tüm yapılandırmaları inşa eden yapı komut dosyası I (test ediyorum 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

Dışında çeşitli derleyici bayraklar arasında test gelen, ben de etrafında testlerin sırasını değiştirme denedim (optimizasyon farklı olduğu için ben de 64-bit karşı 32-bit karşılaştırıldığında ettik). Ama yine de, atan2(0, -1)sürüm hala üst her zaman çıkar.

Oluştur 01/08/2008 saat 06:21
kaynak kullanıcı
Diğer dillerde...                            


23 cevaplar

oy
180

Monte Carlo yöntemi değil Uygun ölçülerde tarafından değil, uzun bir atış, açıkça değil, en hızlı, belirtildiği gibi, bazı büyük kavramlar geçerlidir ama öyle. Ayrıca, tüm aradığınız doğruluğu ne tür bağlıdır. Bildiğim en hızlı π sert kodlu hanesiyle biridir. Baktığımızda Pi ve Pi [PDF] , formüllerin bir yeri vardır.

Yineleme başına yaklaşık 14 basamak - Burada hızlı yakınsayan bir yöntemdir. PiFast , şimdiki en hızlı uygulama, bu formülü kullanır FFT . Kod basittir çünkü ben sadece formülü yazacağım. Bu formül neredeyse tarafından bulundu Ramanujan ve Chudnovsky tarafından keşfedilen . O göz ardı etmek bir yöntem değildir bu yüzden - Asil onun sayının birkaç milyar rakamını hesaplanan gerçekte nasıl olduğunu. Formülünü faktöriyel bölünen, çünkü o zaman avantajlı olacaktır terimleri uzaklaştırmak için hesaplamalar geciktirmek için, hızlı bir şekilde taşma ve olur.

Burada görüntü açıklama girin

Burada görüntü açıklama girin

nerede,

Burada görüntü açıklama girin

Aşağıda ise Brent-Salamin algoritması . Ara zaman söz edilen bir ve b yerleştirilir, daha sonra "yeterince yakın" (a + b) ² / 4t tt bir yaklaşım olur. Ben aracı "yeterince yakın" emin değilim, ama benim testlerden bir yineleme 2 basamak, iki 7 got var ve üç 15 vardı, tabii bu çiftlerde ile, bu yüzden bir hata onun temsile dayalı olabilir ve gerçek hesaplama daha doğru olabilir.

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)

Son olarak, nasıl bazı pi golf (800 hane) hakkında? 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);}
Cevap 02/08/2008 saat 19:22
kaynak kullanıcı

oy
96

Gerçekten kendi alanında bakarak pi yaklaşır bu program gibi :-)

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()
{
            _-_-_-_
       _-_-_-_-_-_-_-_-_
    _-_-_-_-_-_-_-_-_-_-_-_
  _-_-_-_-_-_-_-_-_-_-_-_-_-_
 _-_-_-_-_-_-_-_-_-_-_-_-_-_-_
 _-_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
 _-_-_-_-_-_-_-_-_-_-_-_-_-_-_
 _-_-_-_-_-_-_-_-_-_-_-_-_-_-_
  _-_-_-_-_-_-_-_-_-_-_-_-_-_
    _-_-_-_-_-_-_-_-_-_-_-_
        _-_-_-_-_-_-_-_
            _-_-_-_
}
Cevap 02/09/2008 saat 14:28
kaynak kullanıcı

oy
72

İşte ben lisede öğrenilen pi hesaplamak için bir tekniğin genel bir açıklamasından.

Ben kimsenin süresiz, hatırlayabilmesi yeterince basit olduğunu düşünüyorum çünkü sadece bu paylaşmak, ayrıca size "Monte-Carlo" yöntemlerinin kavramını öğretir - hemen olmaya görünmüyor cevapları geldikten istatistiksel yöntemler rasgele süreçlerle bir sonucu değildir.

Bir kare çizmek ve bu kare içinde bir kadranı (yarı-daire, dörtte birini) kazımak (karenin tarafına eşit yarıçapı olan bir kadran, bu nedenle mümkün olan kare kadar doldurur)

Şimdi meydanda bir ok atmak ve bu topraklar nerede kayıt - yani, her yerde kare içinde rastgele bir nokta seçin. Tabii ki, bu kare içinde indi, ancak yarım daire içinde mi? Bu gerçeği kaydedin.

Bu işlemi birçok kez tekrarlayın - ve atılan toplam sayısı karşısında yarım daire içindeki noktaların sayısının bir oran vardır bulacaksınız bu oran x diyoruz.

karenin alanı r katı r olduğundan, yarı daire alanı x kez kez r (yani, x kez kare r) r olduğu anlaşılmaktadır. Dolayısıyla size pi verecek kez 4 x.

Bu kullanmak için hızlı bir yöntem değildir. Ama bu bir Monte Carlo yönteminin güzel bir örnek. Etrafına bak eğer, size hesaplama becerileri tür yöntemlerle çözülebilir aksi dışarıdaki birçok sorunu bulabilirsiniz.

Cevap 01/08/2008 saat 14:37
kaynak kullanıcı

oy
51

eksiksiz olması için, optimize edilmiş bir derlemesi için derleme zamanında PI hesaplamak ve tek bir değer iç fonksiyon C ++ şablon sürümü.

#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 I> 10 için optimize aynı şekilde optimize edilmemiş ishal için, yavaş olabilir oluşturur. 12 yineleme için I () (memoisation yokluğunda) değerine 80k aramalar yaklaşık olduğuna inanıyoruz.

Cevap 22/12/2009 saat 16:40
kaynak kullanıcı

oy
40

Için (diğer şeyler arasında) adanmış bütün bir kitap aslında var hızlı \ pi hesaplanması yöntemleri: 'Pi ve AGM' (Jonathan ve Peter Borwein tarafından, Kaynak geçerli ).

Ben AGM ve ilgili algoritmalar biraz okudu: o (bazen önemsiz olmayan olsa da) oldukça ilginç.

(Eğer bir çokduyarlıklı aritmetik kütüphane gerekir, o \ pi hesaplamak için en modern algoritmalar uygulamak Not GMP Geçen kullandım çünkü bir süre oldu ama oldukça iyi bir seçimdir).

En iyi algoritmaların zaman karmaşıklığı O M (n) M (n) = O (n iki n-bitlik tamsayı (çoğalması için zaman karmaşıklığı (nM (n) giriş ()) 'dir log (n) giriş (log (n)))) \ pi basamak işlem ve bu tür bir algoritma, GMP uygulandığında, genellikle gerekli olan FFT tabanlı algoritmalar kullanılarak.

algoritmalar arkasında matematik önemsiz olmayabilir rağmen, algoritmalar kendileri genellikle sözde kod birkaç satır vardır ve (eğer :-) kendi çokduyarlıklı aritmetik yazmak için değil seçerseniz) bunların uygulanması genellikle çok basittir unutmayın.

Cevap 24/08/2008 saat 18:14
kaynak kullanıcı

oy
36

Aşağıdaki cevapları kesin mümkün olan en hızlı şekilde bunun nasıl - az hesaplama çabayla . Eğer cevap sevmiyorum bile, gerçekten en hızlı yoludur itiraf etmeliyim olsun Pİ değerini.

HIZLI yolu Pi değerini elde etmektir:

  1. favori programlama dili seçti
  2. 's Matematik kitaplığı yüklenemedi
  3. ve Pi zaten orada tanımlandığını bulmak !! kullanmaya hazır ..

durumda el altında bir matematik kütüphanesi yok ..

İKİNCİ EN HIZLI yolu (daha evrensel çözüm) 'dir:

Burada Internet, eg Pi bakma:

http://www.eveandersson.com/pi/digits/1000000 (1 milyon hane .. sizin kayan nokta hassas nedir?)

Veya burada:

http://3.141592653589793238462643383279502884197169399375105820974944592.com/

Veya burada:

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

Bu Kullanmak istediğiniz ne olursa olsun hassas aritmetik için gereken basamakları bulmak için gerçekten hızlı ve sürekli bir tanımlayarak, size değerli CPU zaman kaybetmeyin emin olabilirsiniz.

Sadece bu kısmen mizahi cevabı, ancak gerçekte, eğer kimse saymazlar .. o CPU zamanı oldukça büyük bir kayıp olur gerçek bir uygulamada devam edin ve Pi değerini hesaplamak ki? En azından ben bu yeniden hesaplamak için çalıştıkları için gerçek bir uygulama görmüyorum.

Değerli Yönetici: OP sorulan unutmayın "En Hızlı Yolu Pİ değerini elde etmek için"

Cevap 28/10/2011 saat 02:02
kaynak kullanıcı

oy
25

BBP formül da :) ilk olarak önceki n-1 basamak ile rahatsız etmeden - 2 tabanı (veya 16) in - n'inci rakamı hesaplamak sağlar

Cevap 29/08/2008 saat 10:22
kaynak kullanıcı

oy
21

Bunun yerine sabit olarak pi tanımlamanın, hep kullanmak acos(-1).

Cevap 08/03/2009 saat 04:02
kaynak kullanıcı

oy
20

Eğer bu yazı doğru ise o zaman Bellard algoritması yarattı en hızlı kullanılabilir biri olabilir. O 2,7 TRİLYON rakam bir MASAÜSTÜ PC kullanarak pi yarattı!

... ve onun yayınladı burada işi

İyi iş Bellard, Bir öncü vardır!

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

Cevap 06/01/2010 saat 13:41
kaynak kullanıcı

oy
20

Sadece şeyiyle burada olmalı bu geldi:

Piet de PI hesaplamak

Bu hassas büyük bir program yaparak geliştirilebilir oldukça güzel özelliği vardır.

İşte 'dilin kendisi verecek bazı konulardan s

Cevap 12/01/2009 saat 19:46
kaynak kullanıcı

oy
19

Bu uygulanması kolay bir "klasik" yöntemidir. Bu uygulama, python (o kadar hızlı dili) yapar:

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)

Sen fazla bilgi bulabilirsiniz burada .

piton olduğu içinde Neyse en hızlı şekilde pi kesin olarak-çok-as-you-yokluk değeri almak için:

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

Burada gmpy pi yöntemi için kaynak parçasıdır, ben kod bu durumda açıklama olduğu kadar kullanışlı olduğunu düşünmüyorum:

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

DÜZENLEME: Ben, kesme ve yapıştırma ve identation ile biraz problem vardı zaten sen kaynağını bulabilirsiniz burada .

Cevap 02/10/2008 saat 22:27
kaynak kullanıcı

oy
17

Eğer en hızlı demek en hızlı tarafından kodunda yazmak için, burada var golfscript çözümü:

;''6666,-2%{2+.2/@*\/10.3??2*+}*`1000<~\;
Cevap 06/08/2008 saat 23:54
kaynak kullanıcı

oy
15

Machin benzeri formülü kullanın

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.

Örneğin, Şemada Uygulanan:

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

Cevap 05/02/2011 saat 06:26
kaynak kullanıcı

oy
15

çiftlerde ile:

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

Bu çifte doldurmaya yetecek kadar 14 ondalık, doğru olacaktır (yay teğetler ondalık sayılar kalan kesik olduğu için yanlışlık muhtemelen).

Ayrıca Seth, bu 3,14159265358979323846 var 3 değil, 64.

Cevap 28/02/2010 saat 04:52
kaynak kullanıcı

oy
15

Eğer bir yaklaşım kullanmaya istekli iseniz, 355 / 1136 ondalık basamak için iyidir ve tamsayı ifadelerle kullanılabilir olma avantajına sahiptir. Yani "nokta matematik işlemcisi kayan" gibi herhangi bir anlama sahip durdurdu, bugünlerde kadar önemli değil, ama bir kez oldukça önemliydi.

Cevap 17/09/2009 saat 17:30
kaynak kullanıcı

oy
15

Pi tam 3'tür! [Prof. Frink (Simpsonlar)]

Şaka, ama burada (gerekli .NET Framework-) C # biri.

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;
        }
    }
}
Cevap 26/02/2009 saat 20:22
kaynak kullanıcı

oy
15

D ile derleme zamanında PI hesaplayın

(Kopyalanan 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))) );
Cevap 17/09/2008 saat 18:49
kaynak kullanıcı

oy
13

(Delphi) Bu versiyon özel bir şey, ama daha az hızlıdır Nick Hodge onun blogda yayınlanan versiyonunda :). Benim makinede, bu değeri veren bir milyar yinelemeleri yapmak için yaklaşık 16 saniye sürer 3.14159265 25879 (doğru parçası kalın harflerle gösterilmiştir).

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.
Cevap 12/01/2009 saat 19:24
kaynak kullanıcı

oy
12

İsterseniz hesaplamak (nedense) tt değerinin bir yaklaşım, bir ikili çıkarma algoritması denemelisiniz. Bellard en iyileştirilmesi BBP O (N ^ 2) 'de PI yapar verir.


Eğer isterseniz elde sonra, hesaplamaları yapmak için tt değerinin bir yaklaşım:

PI = 3.141592654

Verilen bu sadece bir yaklaşım ve tam doğru değil. Biraz daha ,00000000004102 daha yanlış. (dört ile on-trilyonda, yaklaşık 4 / 10,000,000,000 ).


Eğer yapmak istiyorsanız matematik tt, sonra π kendine bir kalem ve kağıt veya bir bilgisayar cebir paketi almak ve tt kesin değeri kullanın.

Eğer gerçekten bir formül istiyorsanız, bu bir eğlenceli:

π = - ı ln (-1)

Cevap 22/12/2009 saat 22:13
kaynak kullanıcı

oy
12

Geri küçük kelime boyutları ve yavaş ya da varolmayan kayan nokta operasyonları ile eski günleri, biz böyle şeyler yapardık:

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

hassas bir sürü gerektirmeyen uygulamalarda (örneğin video oyunları,), bu çok hızlıdır ve yeterince doğrudur.

Cevap 20/02/2009 saat 22:21
kaynak kullanıcı

oy
11

Brent yöntem yukarıda Chris tarafından gönderildi çok iyidir; Brent, genel olarak rasgele hassas aritmetik alanında bir dev.

İstediğin N. haneli ise, ünlü BBP formülü onaltılık yararlıdır

Cevap 04/08/2009 saat 22:39
kaynak kullanıcı

oy
1

daire alanından tt hesaplama :-)

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

Cevap 03/06/2017 saat 17:13
kaynak kullanıcı

oy
0

Daha iyi Yaklaşım

Gibi standart sabitler çıktısını almak için pi veya standart kavramlar, öncelikle kullandığınız dil mevcut yerleşikleri yöntemlerle gitmek gerekir. En hızlı şekilde değer ve aynı zamanda en iyi şekilde dönecektir. Ben değer pi almanın en hızlı yol almak için piton kullanıyorum

  • matematik kütüphanesinin pi değişkeni . Matematik kütüphane değişken pi olarak sabit saklayın.

math_pi.py

import math
print math.pi

linux zaman programı ile komut dosyasını çalıştırın /usr/bin/time -v python math_pi.py

Çıktı:

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
  • matematik yöntemi cos yayı kullanın

acos_pi.py

import math
print math.acos(-1)

linux zaman programı ile komut dosyasını çalıştırın /usr/bin/time -v python acos_pi.py

Çıktı:

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 zaman programı ile komut dosyasını çalıştırın /usr/bin/time -v python bbp_pi.py

Çıktı:

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

Yani en iyi yolu onlar çıktı almak için en hızlı ve en iyi dil nedene tarafından sağlanan yöntemi yerleşiklere kullanmaktır. piton kullanımı Math.PI olarak

Cevap 18/06/2018 saat 10:07
kaynak kullanıcı

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