2012-02-29 58 views
16

Trigonometri için aralık azaltma işlemini uygulamaya çalışıyorum. Ancak bunun yerine, gelen veriler üzerinde sadece bir modulo pi/2 işlemi gerçekleştirmenin daha iyi olabileceğini düşünüyorum. 32-bit IEEE 754 kayan nokta için hangi algoritmaların var olduğunu ve bu işlem için ne kadar verimli olduğunu merak ediyordum?Kayan Nokta Modulo Çalışması

Bunu montajda uygulamak zorundayım, bu yüzden fmod, bölme, çarpma, vb. Sadece bir talimatla mevcut değildir. İşlemcim 16 bit kelimeler kullanıyor ve 32 bit kayan nokta ekleme, çıkarma, çarpma, bölme, karekök, kosinüs ve sinüs uyguladık. Sadece kosinüs ve sinüs değerlerini girmek için aralık küçültmeye (modül) ihtiyacım var.

+4

Aslında "zeki menzil azaltma" için google çok akıllı algoritmalar var ama bence istediğini değil bu – hirschhornsalz

+1

Bir önceki ilgili soruya bağlı Ng tarafından kağıt aslında aslında Payne-Hanek açıklıyor AFAIK'in doğru menzil azaltımı için hala en son teknoloji olduğu algoritması. Sadece tek bir hassasiyete uyarlamanız gerekiyor. – janneb

+0

@Everyone, lütfen yanıtınızı silin/düzenleyin, böylece asıl soruma uygulanmalıdır. Kayan noktalı modül içinde algoritmayı arıyorum. Yaptığım bölülerin sayısını en aza indirir ve fmodu gerçekleştirmem gerekir. – Veridian

cevap

14

Ben standart kütüphane en fmod() çoğu durumda en iyi seçim olacağını düşünüyorum. İşte birkaç basit algoritmanın bir tartışması için bir link. Benim makinede

, fmod() kullanımları optimize satır içi montaj kodu (/usr/include/bits/mathinline.h):

#if defined __FAST_MATH__ && !__GNUC_PREREQ (3, 5) 
__inline_mathcodeNP2 (fmod, __x, __y, \ 
    register long double __value;       \ 
    __asm __volatile__         \ 
    ("1: fprem\n\t"       \ 
    "fnstsw %%ax\n\t"        \ 
    "sahf\n\t"         \ 
    "jp 1b"        \ 
    : "=t" (__value) : "0" (__x), "u" (__y) : "ax", "cc");   \ 
    return __value) 
#endif 

Yani aslında hesaplanması için özel bir işlemci talimatı (fprem) kullanır.

+0

Oh, aslında fmod'in ne yaptığını yapmaya çalışıyorum. Sorun bu, kayan nokta için modül algoritması arıyorum. – Veridian

+0

en doğrudan formu muhtemelen (benim sonrası bağlantıdan alınan kod, ancak bu şekilde bunu yapmanın belirgin yolu kayan nokta için modülünün tanımlanması tür ve) 'dir: template T Fmod (T x T y) { T = (T) (çok uzun) (x/y); dönüş x - a * y; } –

+0

Ben * y ürünün bu konuda yuvarlama konusunda biraz endişeliyim, ama bunu hafifletmek için nasıl emin değilim. – zmccord

12

Belki buradaki noktayı kaçırıyorum, ama sadece fmod kullanarak bir şey var mı?

double theta = 10.4; 
const double HALF_PI = 2 * atan(1); 
double result = fmod(theta, HALF_PI); 
+0

Buraya kadar bir artı değer. –

+0

Oh, aslında fmodin ne yaptığını uygulamaya çalışıyorum. Sorun bu, kayan nokta için modül algoritması arıyorum. – Veridian

+2

'fmod', büyük argümanlar ile hassasiyeti önemsemediğiniz sürece tamamdır. – hirschhornsalz

7

istediğiniz algoritma, 0 ve n bazı katsayıları arasındaki kayan nokta value sınırlamak için: Örneğin pi mod e (3,14159265358979 mod 2,718281828459045)

3.14159265358979/2.718281828459045 
    = 1.1557273497909217179 

Trunc(1.1557273497909217179) 
    = 1 

1.1557273497909217179 - 1 
    = 0.1557273497909217179 

0.1557273497909217179 * e 
    = 0.1557273497909217179 * 2.718281828459045 
    = 0.42331082513074800 

pi mod için

Double fmod(Double value, Double modulus) 
{ 
    return value - Trunc(value/modulus)*modulus; 
} 

e = 0.42331082513074800

+2

çağıran bir döngü vektörize olmaz benim derleyici Bu benim için özellikle yararlı oldu buldu Sabit bir sayı sistemi içinde çalışıyorum. Bunu yayınladığınıza sevindim, çünkü Fmod() OP için yapılmış olsa bile ihtiyaçlarımın bir çözümü değildi. Diğer bağlamlarda bu özel formüle ihtiyaç duyan birkaç kişi var. –

+0

Bu (https://stackoverflow.com/questions/9505513/floating-point-modulo-operation/37977740#comment12038890_9505761) [value's 'büyük için çok hatalı] olabilir. Daha sofistike algoritmalar var. Ama bu genellikle oldukça hızlı olacaktır, bu yüzden kullanım durumunuz için sayısal olarak iyi bir seçimdir. –