C sinüs arama tablosu oluşturmak ++

oy
10

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.

Oluştur 10/09/2010 saat 22:57
kaynak kullanıcı
Diğer dillerde...                            


6 cevaplar

oy
6

Sen isteyeceksiniz std::sin()gelen işlevi <cmath>.

Cevap 10/09/2010 saat 23:00
kaynak kullanıcı

oy
4
long double sine_table[2001];
for (int index = 0; index < 2001; index++)
{
    sine_table[index] = std::sin(PI * (index - 1000) / 1000.0);
}
Cevap 10/09/2010 saat 23:03
kaynak kullanıcı

oy
3


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.

Cevap 11/09/2010 saat 00:29
kaynak kullanıcı

oy
25

[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 (x) = - sin (= X), I kadran IV harita
  • sin (x) = sin (pi - x) I kadranda II'den haritaya

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.

  • sin (x) = x - x ^ 03/03! + X ^ 05/05! ..., nerede ^ a güç ve karşı yükselterek temsil! Faktöriyel temsil eder.

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.

Cevap 11/09/2010 saat 00:55
kaynak kullanıcı

oy
4

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:

  • sin ([n + 1] * a) = sin (n *) * cos (a) + cos (n *) * sin (a)
  • Cos ([n + 1] * a) cos = (n *) * cos (a) - sin (n *) * sin (a)

Bu yöntemin dezavantajı, bu işlem sırasında yuvarlama hata kartı olmasıdır.

Cevap 19/09/2010 saat 18:37
kaynak kullanıcı

oy
3

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);
Cevap 29/03/2013 saat 23:14
kaynak kullanıcı

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