2012-02-29 95 views
16

我正在嘗試實現三角函數的範圍縮減操作。但是,我認爲只需對輸入數據執行模pi/2操作可能會更好。我想知道哪些算法存在,並且對於32位IEEE 754浮點的這種操作是否有效?浮點模數運算

我必須在彙編中實現這個,所以fmod,除法,乘法等等對我來說只有一條指令是不可用的。我的處理器使用16位字,我實現了32位浮點加法,減法,乘法,除法,平方根,餘弦和正弦。我只需要減少範圍(模數)以將值輸入餘弦和正弦。

+4

實際上有很多聰明的算法,例如谷歌的「payne hanek範圍減少」,但我認爲那不是你想要的 – hirschhornsalz 2012-02-29 20:34:44

+1

你在之前的相關問題中鏈接到的Ng的論文實際上解釋了Payne-Hanek算法,該AFAIK仍然是精確縮小範圍的最新技術。你只需要適應單精度。 – janneb 2012-02-29 21:09:48

+0

@所有人,請刪除/編輯您的答案,以便它適用於我的實際問題。我正在尋找浮點模數內的算法。我需要實現fmod的功能,並儘量減少我執行的分割數量。 – Veridian 2012-03-01 16:41:29

回答

14

我認爲標準庫的fmod()將是大多數情況下的最佳選擇。這裏有一個link來討論幾個簡單的算法。

在我的機器,fmod()用途優化聯彙編代碼(/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 

所以它實際上使用用於計算一個專用的CPU指令(FPREM)。

+0

哦,我實際上正在嘗試實現fmod的功能。這是問題,我正在尋找浮點模數算法。 – Veridian 2012-02-29 20:11:53

+0

最直接的形式可能是(我的帖子中的代碼是從鏈接中獲取的,但它是浮點模數的定義,因此也是這樣做的明顯方式):template T fmod(T x,T y) T a =(T)(long long)(x/y); return x - a * y; } – 2012-02-29 20:17:06

+0

我有點擔心這個* y產品四捨五入,但我不確定如何緩解它。 – zmccord 2012-02-29 21:00:52

12

也許我錯過了這裏的觀點,但是 你有什麼反對簡單地使用fmod

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

然後值得讚賞。 – 2012-02-29 20:05:24

+0

哦,我實際上正在試圖實現fmod的功能。這是問題,我正在尋找浮點模數算法。 – Veridian 2012-02-29 20:11:35

+2

只要您不關心大參數的精度,'fmod'就可以。 – hirschhornsalz 2012-02-29 20:31:15

7

你想要的算法,以限制0和一些模量n之間的浮點value

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

例如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模e = 0.42331082513074800

+2

這對我特別有用,因爲 - 雖然最初的問題是在C/C++編程的上下文中提出的,但我遇到了這個需要通用公式的問題在我工作的定點數字系統中。我很高興你發佈了這個,因爲fmod()不是我的需求的解決方案,儘管它可能是針對OP的。在其他情況下,有相當多的人需要這個特定的公式。 – 2016-08-18 06:25:17

+0

這可能[非常不準確的大'價值'](https://stackoverflow.com/questions/9505513/floating-point-modulo-operation/37977740#comment12038890_9505761)。有更復雜的算法。但是這通常會相當快,所以如果它在數值上可以滿足您的使用情況,那麼這是一個不錯的選擇。 – 2017-10-08 02:10:15