繁体   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