web-dev-qa-db-ja.com

浮動小数点モジュロ演算

三角法の範囲縮小操作を実装しようとしています。しかし、代わりに、着信データに対してモジュロpi/2演算を実行する方が良いかもしれないと思います。 32ビットIEEE 754浮動小数点のこの操作にはどのアルゴリズムが存在し、効率的か疑問に思っていましたか?

これをアセンブリに実装する必要があるため、1つの命令だけではfmod、除算、乗算などを使用できません。私のプロセッサは16ビットワードを使用し、32ビット浮動小数点の加算、減算、乗算、除算、平方根、コサイン、サインを実装しています。コサインとサインに値を入力するには、範囲の縮小(モジュラス)が必要です。

21
Veridian

ほとんどの場合、標準ライブラリの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)を計算に使用します。

18

たぶん私はここでポイントを失っていますが、単に fmod を使用することに反対する何かがありますか?

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

0といくつかのモジュラスvalueの間の浮動小数点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

pi mod e = 0.42331082513074800

9
Ian Boyd