2012-02-29 24 views
16

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

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

+4

実際には、 "payne hanek range reduction"のための例googleのための巧妙なアルゴリズムがたくさんありますが、私はあなたが望むものではないと思っています – hirschhornsalz

+1

あなたの以前の関連する質問にリンクしたNgによる論文は実際にPayne- AFAIKは依然として正確な範囲の縮小のための最新技術です。それを単精度に適合させるだけです。 – janneb

+0

@Everyone、私の実際の質問に適用されるように、回答を削除/編集してください。私は、浮動小数点モジュラス内のアルゴリズムを探しています。私はfmodの実装を実装し、実行する分割数を最小限に抑える必要があります。 – Veridian

答えて

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

+0

最も直接的な形式はおそらく(私の記事のリンクから取ったコードですが、浮動小数点のためのモジュラスの定義なので、それを実行する明白な方法です):template T fmod(T x、T (x/y); T a =(T)(long long)(x/y); 戻り値x - a * y; } –

+0

私はその製品の丸めを少し心配していますが、私はそれを緩和する方法がわかりません。 – zmccord

12

多分私はここでポイントを逃しているが、 あなたは単にfmodを使用して何かに対して何かを持っていますか?

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

その時upvoteを価値がある。 –

+0

ああ、私は実際にfmodが何をしているかを実装しようとしています。それは問題です、私は浮動小数点のモジュラスアルゴリズムを探しています。 – Veridian

+2

'fmod'は大きな引数を持つ精度について気にしない限り大丈夫です。 – hirschhornsalz

7

したいアルゴリズム、0nいくつかの係数の間の浮動小数点valueを制限する例: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のための

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

e = 0.42331082513074800

+2

これは特に役に立ちました。最初の質問はC/C++プログラミングのコンテキストで尋ねられましたが、この特定の質問にはこれを行うための一般的な式が必要でした私が働いている固定小数点システムでは、あなたがこれを投稿してうれしく思います.fmod()は私の必要性の解決策ではなかったからです。他の文脈でこの特定の数式を必要とするかなりの数の人々がいます。 –

+0

これは[大規模な 'value's]に対して非常に不正確です(https://stackoverflow.com/questions/9505513/floating-point-modulo-operation/37977740#comment12038890_9505761)。より洗練されたアルゴリズムがあります。しかし、これは通常かなり速いので、あなたのユースケースで数値的に良ければ良い選択です。 –

関連する問題