Nasıl C ++ aşağıdaki pseudocode yeniden yazabilirsiniz?
real array sine_table[-1000..1000]
for x from -1000 to 1000
sine_table[x] := sine(pi * x / 1000)
Ben sine_table arama tablosu oluşturmak gerekir.
Nasıl C ++ aşağıdaki pseudocode yeniden yazabilirsiniz?
real array sine_table[-1000..1000]
for x from -1000 to 1000
sine_table[x] := sine(pi * x / 1000)
Ben sine_table arama tablosu oluşturmak gerekir.
Sen isteyeceksiniz std::sin()gelen işlevi <cmath>.
long double sine_table[2001];
for (int index = 0; index < 2001; index++)
{
sine_table[index] = std::sin(PI * (index - 1000) / 1000.0);
}
double table[1000] = {0};
for (int i = 1; i <= 1000; i++)
{
sine_table[i-1] = std::sin(PI * i/ 1000.0);
}
double getSineValue(int multipleOfPi){
if(multipleOfPi == 0) return 0.0;
int sign = 1;
if(multipleOfPi < 0){
sign = -1;
}
return signsine_table[signmultipleOfPi - 1];
}
Bir hile sin (pi / 2 +/- açısı) = +/- cos (açı) ile, 500 dizi uzunluğu azaltabilir. Yani mağaza günah ve 0'dan pi / 4 Cos. Başımın üstünden hatırlamıyorum ama benim programın hızını artırmıştır.
[0, pi / 2], yani x, sadece birinci kadran için değerlerin depolanması orjinal% 25 için tablo büyüklüğü azaltır.
sizin arama rutin sadece basit trigonometrik kimliklerini kullanarak ilk kadranda x'in bütün değerlerini eşleştirmek için gereken Bunu yapmak için:
sin (pi + x) - I kadranda III'ten haritasını çıkarmak için, her iki kimlikleri, yani sin (x) = uygulamak
Bu strateji yardımcı olsun sizin durumunuzda ne kadar bellek kullanımı konularında bağlıdır. Eğer arama sırasında bir karşılaştırma ve çıkarma ya da iki kaçınmak sadece ihtiyaç olarak Ama dört kat daha fazla değerlerini saklamak için savurgan görünüyor.
Ben ikinci Jeremy'nin öneri bir tablo bina sadece std :: günah kullanmaktan daha iyi olup olmadığını ölçmek için (). Hatta orijinal büyük bir masa bulunan, sen pi / 1000 en yakın artışına argüman dönüştürmek için her bir tablo araması sırasında döngüleri harcamak gerekir ve bu süreçte bazı doğruluğu kaybedersiniz.
Eğer gerçekten hız için doğruluğu ticaret çalışıyorsanız, Taylor serisi genişleme sadece ilk birkaç terimleri kullanarak sin () işlevini yaklaşan deneyebilirsiniz.
x ^ 5 hesaplarken Elbette verimlilik için, sen mesela kullanımını x ^ 3 faktöriyel'dir precompute ve daha yüksek olanları hesaplamak için x'in alt güçlerin kullanmalıdır.
Bir son nokta, kesik Taylor serisi üzerinde sıfıra çok yakın değerler için yaklaşık sinüs hesaplamadan önce ilk ya da dördüncü kadran eşlemek için böylece onun yine değerli daha doğrudur.
İki gözlemlere dayanarak yine bir başka potansiyel gelişme: Ek
ilk oktant içinde sinüs ve kosinüs hem hesaplayabilir eğer 1. Herhangi trigonometri fonksiyonu hesaplayabilir [0, pi / 4]
sıfırda merkezli 2. Taylor seri açılımı olan daha doğru yakın sıfır
Bir kesik Taylor serisini kullanmaya karar, o zaman sizin gibi kullanarak kimlikler [pi / 4, 0] doğruluğunu artırmak (veya benzer doğruluk için daha az terimleri kullanın) aralığında açısını elde etmek için sinüs veya kosinüs ya eslestirin olabilir sin (x) yukarıdaki özelliklere ek olarak cos (pi / 2-x) ve cos (x) = sin (pi / 2-x) = (örneğin, x> pi / 4 eşlenen bir kez eğer ilk kadran.)
Eğer sinüs ve kosinüs ikisi için de bir tablosunun kullanılması karar verirseniz Veya yalnızca aralığı kaplı iki küçük tablolarla tarafından alabilir [0, pi / 4] aramasında başka bir olası karşılaştırma ve çıkarma pahasına eşlemek Daha küçük olan aralık. Sonra tablolar için daha az bellek kullanmak veya aynı bellek kullanmasına ama daha parçalı yapı ve doğruluğu sağlayabilir ya.
Bir sayı daha: trigonometrik fonksiyonlar çağırarak pahalı. Eğer sürekli adımla sinüs için arama tablosu hazırlamak istiyorsanız - Eğer bazı potansiyel hassas kaybı pahasına içinde, hesaplama zamandan tasarruf edebilir.
Lütfen en az adımı düşünün "a" dır. Yani sin (a) sin (2a), sin (3a) ihtiyaç olduğunu ...
Sonra aşağıdaki yöntemi olabilir: Birincisi sin hesaplamak (a) ve cos (a). Sonra her ardışık adım için aşağıdaki trigonometrik Eşitlikler kullanın:
Bu yöntemin dezavantajı, bu işlem sırasında yuvarlama hata kartı olmasıdır.
Bir kitap ya da bir şey başka bir yaklaşım
streamin ramp;
streamout sine;
float x,rect,k,i,j;
x = ramp -0.5;
rect = x * (1 - x < 0 & 2);
k = (rect + 0.42493299) *(rect -0.5) * (rect - 0.92493302) ;
i = 0.436501 + (rect * (rect + 1.05802));
j = 1.21551 + (rect * (rect - 2.0580201));
sine = i*j*k*60.252201*x;
Burada tam tartışması: http://synthmaker.co.uk/forum/viewtopic.php?f=4&t=6457&st=0&sk=t&sd=a
Sana bir bölünme kullanılarak ondalık sayı ile çarpılması daha çok yavaş olduğunu, biliyoruz farz / 5 * 0.2 den daima daha yavaştır
bu sadece bir tahmindir bu.
Ayrıca:
streamin ramp;
streamin x; // 1.5 = Saw 3.142 = Sin 4.5 = SawSin
streamout sine;
float saw,saw2;
saw = (ramp * 2 - 1) * x;
saw2 = saw * saw;
sine = -0.166667 + saw2 * (0.00833333 + saw2 * (-0.000198409 + saw2 * (2.7526e-006+saw2 * -2.39e-008)));
sine = saw * (1+ saw2 * sine);