浮点模数运算

Ver*_*ian 21 c floating-point binary assembly modulo

我正在尝试实现三角学的范围缩减操作.但相反,我认为对输入数据执行模数pi/2操作可能会更好.我想知道什么算法存在并且对于32位IEEE 754浮点的这种操作有效?

我必须在汇编中实现它,所以只用一条指令就不能使用fmod,除法,乘法等.我的处理器使用16位字,我实现了32位浮点加法,减法,乘法,除法,平方根,余弦和正弦.我只需要范围缩减(模数)来输入余弦和正弦值.

Mic*_*ski 18

我认为标准库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
Run Code Online (Sandbox Code Playgroud)

因此它实际上使用专用CPU指令(fprem)进行计算.

  • 遗憾的是,很明显的方法对于大x来说非常不准确.fprem更好,但也不提供"最后一位"准确性,因为Payne-Hanek算法是首选工具. (2认同)

Pra*_*mar 15

也许我在这里忽略了这一点,但你有什么反对简单地使用fmod吗?

double theta = 10.4;
const double HALF_PI = 2 * atan(1);
double result = fmod(theta, HALF_PI);
Run Code Online (Sandbox Code Playgroud)

  • 哦,我实际上正在尝试实现 fmod 的功能。这就是问题,我正在寻找浮点的模数算法。 (2认同)
  • 只要你不关心大参数的精度,`fmod`就可以了. (2认同)
  • 除非 OP 谈论的是 fmod 不可用的环境。 (2认同)

Ian*_*oyd 9

你想要的算法,来限制浮点value之间0有些模量n:

Double fmod(Double value, Double modulus)
{
    return value - Trunc(value/modulus)*modulus;
}
Run Code Online (Sandbox Code Playgroud)

例如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
Run Code Online (Sandbox Code Playgroud)

pi mod e = 0.42331082513074800

  • 这对我来说特别有用,因为 - 虽然最初的问题是在C/C++编程的背景下提出的,但是我提到了这个特殊的问题需要一个通用的公式,在我正在使用的定点数系统中这样做.我很高兴你发布了这个,因为fmod()并不能解决我的需求,即使它可能是针对OP的.在其他情况下,有不少人需要这种特殊的配方. (3认同)