2

ルックアップ テーブルの形式で float 除算の逆数を作成することは可能ですか (1/f -> 1*inv[f] など) ? どのようにそれを行うことができますか?一部とマスクとシフトをフロートに適用して、インデックスの形式にする必要があると思いますか? 正確にはどうですか?

4

3 に答える 3

7

次のようなおおよその逆数を推測できます。

int x = bit_cast<int>(f);
x = 0x7EEEEEEE - x;
float inv = bit_cast<float>(x);

私のテストでは、0x7EF19D07 の方がわずかに優れていました (2 つのニュートン ラフソン改良の効果を含めてテストしました)。

Newton-Raphson を使用して改善できます。

inv = inv * (2 - inv * f);

必要なだけ繰り返します。2 ~ 3 回繰り返すと、良い結果が得られます。

より良い初期近似

相対誤差を最小限に抑えるには:

  • 0x7EF311C2 (洗練なし)
  • 0x7EF311C3 (1 リファインメント)
  • 0x7EF312AC (2 つの改良)
  • 0x7EEEEBB3 (3 リファインメント)

1 と 2 の間の入力の絶対誤差を最小限に抑えるには (その範囲外では十分に機能しますが、最適ではない可能性があります)。

  • 0x7EF504F3 (絞り込みなし)
  • 0x7EF40D2F (1 リファインメント)
  • 0x7EF39252 (2 つの改良)

3 つの改良ステップでは、初期近似は最大相対誤差にほとんど影響しません。0x7EEEEEEEE はうまく機能し、これ以上のものは見つかりませんでした。

于 2012-09-01T13:38:41.117 に答える
4

1 つの方法は次のとおりです。

  1. 入力から符号、指数、仮数を抽出する
  2. 最も重要な仮数ビットのいくつかを使用して、テーブルで逆数を検索します
  3. 指数を否定し、仮数のスケールの変更を調整します
  4. 符号、指数、および仮数を再結合して出力を形成します

ステップ 2 では、使用するビット数を選択し、精度とテーブル サイズの間でトレードする必要があります。下位ビットを使用してテーブル エントリ間を補間することで、精度を高めることができます。

ステップ 3 では、入力仮数が (0.5, 1.0] の範囲にあり、その逆数が [1.0, 2.0] の範囲にあり、出力仮数を得るために再正規化が必要なため、調整が必要です。

これについてはコードを書きません。おそらく、見逃してしまうような、やや厄介なエッジ ケースがいくつかあるからです。

また、数値計算を含む方法も調査する必要があります。これにより、メモリ アクセスが遅い場合により良い結果が得られる可能性があります。最新の PC アーキテクチャでは、キャッシュ ミスは数十回の算術演算と同じくらい高くつく可能性があります。ウィキペディアは良い出発点のようです。そしてもちろん、何をするにしても、実際に FPU の除算演算よりも高速であることを確認するために測定します。

于 2012-09-01T11:39:51.063 に答える
1

最小ステップが 0.01 のようなものである場合、テーブルから逆 f をサポートできます。各インデックスは 100 倍されるので、

table[1]----->1.0/0.01
table[3]----->1.0/0.03
table[105]--->1.0/1.05
...
table[10000]->1.0/100.0


10000 elements for a range of (0.00,100.00)

より高い精度が必要な場合は、より多くのラムが必要になります。

もう一つの例:

range................: 0.000 - 1000.000
minimum increments ..: 0.001
total element number.: 1 million

something like this: table[2343]=1.0/2.343

もう一つの例:

range................: 0.000000 - 1.000000
minimum increments ..: 0.000001
total element number.: 1 million

something like this: table[999999]=1.0/0.999999
于 2012-09-01T11:07:24.493 に答える