簡體   English   中英

浮點模運算

[英]Floating Point Modulo Operation

我正在嘗試實現三角函數的范圍縮減操作。 但相反,我認為對傳入數據執行模 pi/2 操作可能會更好。 我想知道什么算法存在並且對於 32 位 IEEE 754 浮點運算有效?

我必須在匯編中實現這一點,所以只有一條指令就無法使用 fmod、除法、乘法等。 我的處理器使用 16 位字,並且我已經實現了 32 位浮點加法、減法、乘法、除法、平方根、余弦和正弦。 我只需要范圍縮減(模數)來輸入余弦和正弦值。

我認為標准庫的fmod()將是大多數情況下的最佳選擇。 這是幾個簡單算法的討論鏈接

在我的機器上, 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)進行計算。

也許我在這里錯過了重點,但是您是否反對簡單地使用fmod

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

您想要的算法將浮點value限制在0和某個模數n

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

圓周率模式 e = 0.42331082513074800

精確的fmod是用長除法實現的。 確切的余數總是可以表示為被除數和除數共享相同的格式。 您可以查看 glibc 和 musl 等開源實現。 我也做了一個金屬的 (無恥的插頭)

Payne-Hanek 范圍縮減適用於像 π 這樣的常數除數,我們預先存儲了它的倒數。 因此,這里不適用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM