2010-12-11 5 views
6

私はおよそ対数目盛にマップしたい32から8191の範囲の整数値を持っています。ベース2を使用していた場合は、先行ゼロビットを数えて8スロットにマップすることができますが、これはあまりにも粗雑です。私は32スロットが必要です(そしてもっと良くなるでしょうが、私はそれらを32ビットの値でビットにマップする必要があります)。これは対数の約1.18-1.20になります。誰でもこの値を計算するためのいくつかのトリック、または合理的な近似を、非常に速く持っていますか?特別な場合の高速整数の対数

私の直感は、条件付きで2つまたは3つの部分範囲に分割し、それぞれに小さなルックアップテーブルを使用していますが、結果を精算すると、特に結果が正確ではなく、大まかに対数である必要があるためです。

答えて

4

先頭ビット以外の次の2ビットは使用しないでください。最初に番号を8ビンに分割し、次の2ビットを各ビンを4にさらに分割することができます。この場合、非常に高速な単純なシフト操作を使用することができます。

を編集します。対数を使用すると実行可能な解決策だと思う場合は、

aを対数の底とし、範囲は(b_min, b_max) = (32,8191)です。あなたは式を使用してベースを見つけることができます:あなたa~1.1892026を与える

log(b_max/b_min)/log(a) = 32 bin 

を。これを対数の基数として使用する場合は、範囲(b_min, b_max)(log_a(b_min), log_a(b_max)) = (20.0004,52.0004)にマップできます。

今度は、範囲(0,32)を得るには、20.0004ですべての要素を減算するだけです。これは、すべての要素が対数的に均一であることを保証します。完了

:数値エラーのため要素が範囲外になることがあります。あなたはそれを正確に計算する必要があります。

注2:log_a(B)=ログ(B)/ログ(a)の

+0

私は(dlmallocが頭に浮かぶ)の前に行って何かを見てきましたが、私はそれは対数から外れてどのくらい好きかどうかは知りません。たぶんそれは悪いことではないでしょう。 –

+0

浮動小数点を使用して、それらのビットをうまく組み立てることができるのだろうか... –

2

表検索がそのテーブルは、大きくはありません、一つの選択肢です。 8Kのテーブルが大きすぎて、ゼロに先行するカウントがある場合は、上位のビットでテーブルルックアップを使用できます。

nbits = 32 - count_leading_zeros(v) # number of bits in number 
highbits = v >> (nbits - 4)   # top 4 bits. Top bit is always a 1. 
log_base_2 = nbits + table[highbits & 0x7] 

あなたは

table[i] = approx(log_2(1 + i/8.0)) 

あなたは、整数演算での滞在に便利係数で最後の行を乗算する場合log_2

のいくつかの近似値を取り込むテーブル。

+0

8kテーブルは大きすぎますが、8-32エントリのテーブルは悪くないでしょう。私はhwlauの解決策のシンプルさが好きです。 –

+0

私のソリューションは事実上同じです(私の次の3ビットを使用しますが、これは設定可能です)。 –

2

回答私は、IEEE 754に基づいて、浮動小数点を思い付いた:それは(hwlauの答えと同じ)およそ対数0-31に32から8192をマップ

((union { float v; uint32_t r; }){ x }.r >> 21 & 127) - 16 

改良版(役に立たないビット単位と切り出す)を:

((union { float v; uint32_t r; }){ x }.r >> 21) - 528 
+0

他の数のビンにどのように再スケーリングするのですか? – unsym

+0

Rescale .......? –

関連する問題