log(base 2)関数を書く方法はありますか?
C言語には2つの組み込み関数があります->>
1. log
ベースeです。
2. log10
ベース10;
しかし、私はベース2のログ関数が必要です。これを計算する方法。
log(base 2)関数を書く方法はありますか?
C言語には2つの組み込み関数があります->>
1. log
ベースeです。
2. log10
ベース10;
しかし、私はベース2のログ関数が必要です。これを計算する方法。
回答:
C99は持っているlog2
(と同様にlog2f
してlog2l
floatとlong double型のため)。
積分結果を探している場合は、値に設定されている最上位ビットを特定して、その位置を返すことができます。
Integer.highestOneBit(int)
方法は):i |= (i >> 1); i |= (i >> 2); i |= (i >> 4); i |= (i >> 8); i |= (i >> 16); return i - (i >>> 1);
while (i >>= 1) { ++l; }
i>>32
ます。ただし、Javaには32ビットのintしかないため、問題ありません。C / C ++の場合は、考慮する必要があります。
http://en.wikipedia.org/wiki/Logarithmに記載されているように:
logb(x) = logk(x) / logk(b)
つまり:
log2(x) = log10(x) / log10(2)
log()
実装それは行いません。私の悪い。
log10()
関数はC標準で定義されているため、コンパイラは結果を事前計算することを含め、「特別に」自由に処理できます。これは、@ Johannesの提案だったと思いますか?
log10(2)
は定数に置き換えられました。
高速にしたい場合は、Bit Twiddling Hacksのようなルックアップテーブルを使用できます(整数log2のみ)。
uint32_t v; // find the log base 2 of 32-bit v
int r; // result goes here
static const int MultiplyDeBruijnBitPosition[32] =
{
0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30,
8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31
};
v |= v >> 1; // first round down to one less than a power of 2
v |= v >> 2;
v |= v >> 4;
v |= v >> 8;
v |= v >> 16;
r = MultiplyDeBruijnBitPosition[(uint32_t)(v * 0x07C4ACDDU) >> 27];
さらに、ハードウェアで完全に計算される可能性があるため、より高速に_BitScanReverse
なる可能性のあるコンパイラ組み込みメソッドを確認する必要があります。
C ++で整数log2()を実行する方法についても確認してください。
uint16_t log2(uint32_t n) {//but truncated
if (n==0) throw ...
uint16_t logValue = -1;
while (n) {//
logValue++;
n >>= 1;
}
return logValue;
}
基本的にはtomlogicと同じです。
math.h(C)またはcmath(C ++)を含める必要があります。もちろん、私たちが知っている数学を実行する必要があることを覚えておいてください... 0より大きい数値のみです。
例:
#include <iostream>
#include <cmath>
using namespace std;
int main(){
cout<<log2(number);
}
最上位ビットの位置よりも高い精度が必要であり、使用していたマイクロコントローラーには数学ライブラリがありませんでした。正の整数値の引数に2 ^ n値間の線形近似を使用するだけでうまくいくことがわかりました。これがコードです:
uint16_t approx_log_base_2_N_times_256(uint16_t n)
{
uint16_t msb_only = 0x8000;
uint16_t exp = 15;
if (n == 0)
return (-1);
while ((n & msb_only) == 0) {
msb_only >>= 1;
exp--;
}
return (((uint16_t)((((uint32_t) (n ^ msb_only)) << 8) / msb_only)) | (exp << 8));
}
私のメインプログラムでは、整数の結果でN * log2(N)/ 2を計算する必要がありました。
temp =(((uint32_t)N)* approx_log_base_2_N_times_256)/ 512;
すべての16ビット値が2%以上ずれることはありません