0

float、、にfマップしたい 1 から 0 の範囲にありintますifに関連しiています:

f = 1/(2^i)

それで

i = log2(1/f)

私は計算するために以下を使用していますi

int i = log2f(floorf(1/f)); 

この式には 3 つの float 操作が含まれているため、比較的非効率的であると思います。

私の質問:

  1. 一般的に言えば、これは非効率的ですか?(プラットフォームに依存する最適化のため、これは答えにくいことを理解しています)
  2. より効率的なアルゴリズムを作成することは可能ですか? これには、 s とビット シフト2^nを使用して、より効率的なアルゴリズムを作成できると思います。int
4

5 に答える 5

3

fが正であると仮定すると、はとlog2(1/f)同等になり-log2(f)ます。これにより、少し単純化できます。

int i=floorf(-log2f(f));

除算の代わりに否定を使用すると、速度が大幅に向上する可能性があります。

完全に移植性のないコードを気にしない場合は、浮動小数点数の指数部分を直接抽出できるはずです。の優れた実装log2fはおそらくすでにそれを行っているので、見返りとして移植性をほとんどまたはまったく諦めている可能性があります。

于 2012-05-16T20:48:09.763 に答える
2

float がどのように格納されているかを調べる必要があります。float を格納するために 4 バイトを使用する典型的なマシンでは、最後の 1 バイトはバイナリ指数を格納するために使用されます。メモリのその部分にアクセスできれば、ほぼ完了です。

例えば。C では、1 つの float または 4 つの short unsigned int (1 バイト/short int) を格納する共用体構造を宣言できます。float を割り当てて、指数を格納する short int を抽出するだけです)。

この回答に記載されている実際の値は、お使いのマシンでは正しくない可能性がありますが、正しい数値がわかっている場合は、このアプローチを使用できます。

于 2012-05-16T20:49:35.103 に答える
1

私がこれをまっすぐにしたかどうか見てみましょう。f = 0.5、1 / f = 2の場合、iを1にする必要があります。fが0.5より大きい場合、1 / fは2未満になるため、iは0になります。

For 0.5<f<=1     i=0
For 0.25<f<0.5   i=1
For 0.125<f<0.25 i=2
and so on.

したがって、iは基本的に、仮数の最初の1ビットのゼロベースのインデックスです(指数を考慮に入れると、それに追加する必要があります)

于 2012-05-16T20:47:06.303 に答える
1

では、浮動小数点が IEEE754 標準に従っており、値が正しく計算されていると仮定しましょう。(は常に 2 の累乗であるfloatため、値を として正しく表すことができます。)f

IEEE754 規格を見ると、数値のf仮数は常に* 1.0 になるため、本当に必要なのは指数を抽出することです。これは、 のバイナリ表現を使用して行うことができますfloat。数値自体は 32 ビットであり、指数はビット 24 ~ 31 (右から左に数えます) にあります。値から 127 を引く必要があります。

詳細については、たとえば、このオンライン コンバーターおよび IEEE754 標準に関するドキュメントを参照してください。


*まあ、非正規化された場合を除いて。非正規化された float は1*2^-2、 ではなく のように格納されるもの0.5*2^-1です。非正規化された浮動小数点数を処理するには、0.0 を追加して正規化された浮動小数点数に変換することをお勧めします。あなたの場合、仮数が1ではないことで、非正規化された浮動小数点数を簡単に検出できます。

于 2012-05-17T11:44:23.700 に答える
1

C には、この目的のための関数 frexpf (1999 C 標準セクション 7.12.6.4) があります。指数が [1/2, 1) の分数に一致するように正規化するため、指数から 1 を引く必要があります (たとえば、.25f の場合、.25f = .5 * 2 であるため、指数は -1 になります)。-1ですが、-2 が必要です):

#include <math.h>
#include <stdio.h>


int main(void)
{
    int exponent;
    for (float f = 0x1p-149f; f <= 1; f += f)
    {
        frexpf(f, &exponent);
        printf("The exponent of %a is %d.\n", f, exponent-1);
    }

    return 0;
}
于 2012-05-17T14:34:17.630 に答える