SORU
25 HAZİRAN 2011, CUMARTESİ


Tamsayı olmayan üs?sabit olan pow() iyileştirmeleri

pow() geçici yürütme zamanımın -20 alarak yaptığım Şifremi sıcak noktalar var.

pow(x,y) Giriş benim için çok özeldir, eğer daha yüksek performans pow() iki yakın (her üs için bir rulo bir yolu varsa ben de merak ettim:

  • İki sabit üslü var: 1/2 2.4.4.
  • Üs 2.4 . ancak o zaman ^em>xaralığında (0.090473935, 1.0] olacaktır.
  • Üs 1/2 olduğunda.4,xaralığında (0.0031308, 1.0] olacaktır.
  • SSE/AVX float vektörler kullanıyorum. Eğer platform özellikleri, faydalanabileceğiniz, sağ tarafta!

0.01% maksimum hata oranı tam kesinlik (float) algoritmaları de ilgileniyorum ama idealdir.

Zatenpow() 51**ama bu kısıtlamaları dikkate almaz bir hızla kullanıyorum. Daha iyisini yapmak mümkün müdür?

CEVAP
25 HAZİRAN 2011, CUMARTESİ


Bu nedenle başka bir cevap daha önceki cevabımı çok farklıdır, ve bu hızlı yanan. Bağıl hata 3e-8. Daha fazla hassasiyet ister misin? Bir kaç tane daha Chebychev terimleri ekleyin. En iyi sipariş 2^n-epsilon ve 2^n epsilon arasındaki bu küçük bir süreksizlik için yapar gibi garip.

#include <stdlib.h>
#include <math.h>

// Returns x^(5/12) for x in [1,2), to within 3e-8 (relative error).
// Want more precision? Add more Chebychev polynomial coefs.
double pow512norm (
   double x)
{
   static const int N = 8;

   // Chebychev polynomial terms.
   // Non-zero terms calculated via
   //   integrate (2/pi)*ChebyshevT[n,u]/sqrt(1-u^2)*((u 3)/2)^(5/12)
   //   from -1 to 1
   // Zeroth term is similar except it uses 1/pi rather than 2/pi.
   static const double Cn[N] = { 
       1.1758200232996901923,
       0.16665763094889061230,
      -0.0083154894939042125035,
       0.00075187976780420279038,
      // Wolfram alpha doesn't want to compute the remaining terms
      // to more precision (it times out).
      -0.0000832402,
       0.0000102292,
      -1.3401e-6,
       1.83334e-7};

   double Tn[N];

   double u = 2.0*x - 3.0;

   Tn[0] = 1.0;
   Tn[1] = u;
   for (int ii = 2; ii < N;   ii) {
      Tn[ii] = 2*u*Tn[ii-1] - Tn[ii-2];
   }   

   double y = 0.0;
   for (int ii = N-1; ii >= 0; --ii) {
      y  = Cn[ii]*Tn[ii];
   }   

   return y;
}


// Returns x^(5/12) to within 3e-8 (relative error).
double pow512 (
   double x)
{
   static const double pow2_512[12] = {
      1.0,
      pow(2.0, 5.0/12.0),
      pow(4.0, 5.0/12.0),
      pow(8.0, 5.0/12.0),
      pow(16.0, 5.0/12.0),
      pow(32.0, 5.0/12.0),
      pow(64.0, 5.0/12.0),
      pow(128.0, 5.0/12.0),
      pow(256.0, 5.0/12.0),
      pow(512.0, 5.0/12.0),
      pow(1024.0, 5.0/12.0),
      pow(2048.0, 5.0/12.0)
   };

   double s;
   int iexp;

   s = frexp (x, &iexp);
   s *= 2.0;
   iexp -= 1;

   div_t qr = div (iexp, 12);
   if (qr.rem < 0) {
      qr.quot -= 1;
      qr.rem  = 12;
   }

   return ldexp (pow512norm(s)*pow2_512[qr.rem], 5*qr.quot);
}

Burada Neler oluyor? ek:
İsteği üzerine, aşağıdaki yukarıdaki kod nasıl çalıştığını açıklar.

Genel bakış
Yukarıdaki kod iki işlev, double pow512norm (double x) double pow512 (double x) tanımlar. İkinci paketi için giriş noktası olduğunu, Bu kullanıcı kodu x^(5/12) hesaplamak için çağrı gerektiğini işlevidir. İşlevi pow512norm(x) aralığında x [1,2] yaklaşık x^(5/12), ama sadece Ortalama polinom kullanır. (Bu aralığın dışında x değerleri için pow512norm(x) kullanım ve sonuç çöp olacak.)

pow512(x) 1 rs< gibi bir çift (double s, int n) x = s * 2^n gibi içine ve gelen x böler işlevi;2. n = 12*q r r (int q, unsigned int r) n daha da bölümleme az 12 parçaya x^(5/12) bulma sorunu beni split sağlar:

  1. x^(5/12)=(s^(5/12))*((2^n)^(5/12)) ) (u*v) (u^a)=*(v^a) pozitif u,v ve gerçek bir^.
  2. s^(5/12) pow512norm(s) üzerinden hesaplanır.
  3. Değiştirme) (2^n)^(5/12)=(2^(12*q r))^(5/12).
  4. Olumlu u u^(a b)=(u^a)*(u^b) gerçek,üzerinden 2^(12*q r)=(2^(12*q))*(2^r) b.
  5. Biraz daha manipülasyonlar yoluyla (2^(12*q r))^(5/12)=(2^(5*q))*((2^r)^(5/12)).
  6. (2^r)^(5/12) arama tablosu pow2_512 ile hesaplanır.
  7. pow512norm(s)*pow2_512[qr.rem] hesaplamak ve neredeyse geldik. Burada qr.rem r değeri yukarıdaki adım 3'ü olarak hesaplanır. Bütün gereken, 2^(5*q) Bu istenilen sonuç vermeye çarpın.
  8. Aynen matematik kütüphane işlevi ldexp yapıyor.

Fonksiyon Yaklaşımı
Burada amaç f kolay hesaplanabilir bir yaklaşım(x)=x^(5/12) " el at. sorun için yeterince iyi ile gelmek olduğunu Bizim yaklaşım f(x) bir anlamda yakın olmalıdır. Retorik bir soru: Ne istiyor 'yakın' demek? İki rakip yorumların ortalama Kare hatası minimize karşı maksimum mutlak hata en aza indirmek.

Bunlar arasındaki farkı açıklamak için borsa bir benzetme kullanacağım. Sonunda emeklilik için tasarruf için istediğinizi varsayalım. Eğer yirmili yaşlarda iseniz, yapılacak en iyi şey, hisse senedi veya hisse senedi piyasası fonları yatırım yapmak. Bu bir zaman yeterince uzun bir zaman dilimi içinde, ortalama borsa diğer yatırım planı atıyor çünkü. Ancak, tüm stokları içine para koyarak yapmak çok kötü bir şey olduğunda kez gördük. Eğer ellili veya altmışlı (ya da kırklı eğer emekli olmak istiyorsanız genç) eğer biraz daha dikkatli yatırım yapmak gerekir. Bu downswings emeklilik Portföyü üzerinde yol açabilir.

Geri yaklaşım fonksiyonu: bazı yaklaşımlar tüketici Olarak, genellikle performans yerine en kötü durum hatası hakkında endişe duyuyor "ortalama". Kullanın bazı yaklaşım inşa vermek en iyi performansı "ortalama" (örn: en küçük kareler) ve Murphy kanunları dikte programı-ecek harcamak çok fazla zaman kullanarak yaklaşık tam olarak nerede performansı çok daha kötü ortalama. Ne istediğinizi minimax bir yaklaşım, bazı etki alanı üzerinde maksimum mutlak hata en aza indirir. İyi bir matematik Kütüphanesi bu matematik kitaplığı yazarlarından izin verir, çünkü en küçük kareler yaklaşımı yerine minimax bir yaklaşım kütüphanesinde bazı performans garantisi verecektir.

Matematik kitaplıkları genellikle bir polinom veya bazı işlev f(x) etki alanı: R x R b üzerinden yaklaşık akılcı bir polinom kullanın. Sanırım fonksiyonu f(x) analitik üzerinde bu etki alanı ve yaklaşık işlevi tarafından bazı polinom p(x) derecesi N İçin belirli bir derecesi N var büyülü, benzersiz bir polinom p(x) p(x)-f(x) N 2 B i üzerinde [a,b] ve bu mutlak değerler bunlar N 2 B i hepsi eşit. Bu büyülü polinom p(x) fonksiyonu bulma approximators kutsal kasesidir.

Senin için Kutsal Kase bulamadık. Ben bunun yerine Ortalama bir yaklaşım kullanılır. İlk biraz Ortalama, polinom fonksiyon yaklaşımı konusunda çok güzel bazı özellikleri ile polinomların (ama birimdik) ortogonal bir küme. Ortalama dağılımına çoğu zaman büyülü polinom p(x) çok yakındır. (Aslında, bu Kutsal Kase polinom bulmaması exchange Remez algoritması Genellikle Ortalama bir yaklaşım ile başlar.)

pow512norm(x)
Bu fonksiyon, Ortalamadan yaklaşık x^(5/12) yaklasik bazı polinom p*(x) bulmak için kullanır. Burada p*(x) büyülü polinom p(x) yukarıda açıklanan bu Ortalamadan yaklaşım ayırt etmek için kullanıyorum. Ortalamadan yaklaşık p*(x) bulmak için kolay; p(x) bulma ayı. Ortalama yaklaşık p*(x) sum_i Cn[i]*Tn(i,x), Cn[i] Ortalama katsayıları ve Tn(i,x) Ortalama polinom x değerlendirdi.

Wolfram alpha Ortalama katsayıları benim için Cn bulmak için kullandım. Örneğin, this calculates Cn[1] için. Giriş kutusu sonra ilk kutuyu istenilen cevap, 0.166658 bu durumda. Bunun gibi pek çok rakam değil. 'Basamak' ve işte, daha bir sürü basamak olsun. Wolfram alpha ücretsiz; ne kadar yapacak bir sınırı yoktur. Yüksek mertebeden açısından bu sınır vurur. Eğer satın alırsanız (veya Sturm erişimi hassas yüksek derecede yüksek mertebe bu katsayıları hesaplamak mümkün olacak.)

Tn Ortalama polinom(x) dizi Tn hesaplanır. Ötesini çok yakın büyülü polinom p(x), başka bir nedenle kullanarak Ortalamadan yaklaşık değerleri bu Ortalamadan ifade edilir kolayca hesaplanır: Başlangıç Tn[0]=1 Tn[1]=x ve sonra yinelenen hesaplamak Tn[i]=2*x*Tn[i-1] - Tn[i-2]. (Kullandım 'dizin' 'ben' benim kod. ziyade değişken ıı Ben hiç 'ben' bir değişken adı olarak kullanılıyor. Kaç İngilizce olarak bir 'ben' sözcüğü? İki ardışık var Peki?)

pow512(x)
pow512 kullanıcı kodu arayabilir fonksiyonudur. Ben zaten yukarıda bu fonksiyonu temellerini nitelendirdi. Daha bir kaç detay: matematik kütüphane fonksiyonu frexp(x) significand s ve üs giriş için iexp x döndürür. (Küçük sorun: s pow512norm frexp ile kullanmak için 1 ila 2 0.5 arasında bir değer ve 1. döner istiyorum Matematik Kütüphanesi harika bir çapraz masaüstü güvenlik div döndürür tamsayı bölme için bölüm ve kalan fonksiyon. Son olarak, matematik kitaplığı ldexp üç parça birlikte son cevap şeklinde koymak işlevi kullanın.

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • Charles Renaud

    Charles Rena

    10 Kasım 2007
  • 趣味そうこ♪

    趣味そう

    3 Mart 2010
  • Microsoft Help & Training Videos

    Microsoft He

    31 Mart 2009