如何用c / c ++写日志库(2)
有没有办法写日志(基2)的function?
C语言有2个内置函数 – >>
1.基本的log
2. log10
base 10;
但是我需要base 2的日志function。如何计算这个。
简单的math:
log 2 ( x )= log y ( x )/ log y (2)
其中y可以是任何东西,对于标准日志function是10或者e 。
如果你正在寻找一个完整的结果,你可以确定在该值设置的最高位,并返回其位置。
#define M_LOG2E 1.44269504088896340736 // log2(e) inline long double log2(const long double x){ return log(x) * M_LOG2E; }
(乘法可能快于除法)
C99有log2
(以及log2f
和log2l
用于float和long double)。
正如http://en.wikipedia.org/wiki/Logarithm所述; :
logb(x) = logk(x) / logk(b)
意思就是:
log2(x) = log10(x) / log10(2)
log2(int n) = 31 - __builtin_clz(n)
如果你想让速度更快,你可以使用类似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
这样的编译器内build方法,它可以更快,因为它可能完全用硬件计算。
也看看可能的重复如何做一个整数log2()在C + +?
log2(x) = log10(x) / log10(2)
你必须包括math.h(C)或cmath(C ++)当然要记住,你必须遵循我们知道的math…只有数字> 0。
例:
#include <iostream> #include <cmath> using namespace std; int main(){ cout<<log2(number); }
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库。 我发现只使用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%
咨询你的基础math课程, log n / log 2
。 在这种情况下,selectlog
还是log10
并不重要,除以新的base的log
就行。