最近因为某一些原因,需要要求高速计算一下常用对数的值。但是自然对数的快速算法和常用对数的快速算法都没想到......只得去找那个以2为底的对数值的快速运算方法了,由于精度要求不高(大约0.1即可),固可以尝试这种方案。
因为直接把float数据按照整数来读取,得到的值大约是满足这个式子:
其中σ是一个无限小的数据,经过推导值大约是0.0450466,但是这个只是理论。实际却并非如此,我尝试出来的这个值大约是0.0719附近。
#define POW223 8388608.0 // 2^23
double __log2(float x)
{
long *a;
double o;
a = (long*)&x; // 强制的位转换
o = (double)*a;
// ???实际证明那个0.04几的值误差非常大....
o = o / POW223 - 126.928071372;
return o;
}
我测试了[1, 2000]上的所有正整数,其值误差都在0.1以内:
int main()
{
int i;
for (i = 1; i <= 2000; i++)
{
double diff;
diff = log2(i) - __log2(i);
printf("%.10lf\n", diff);
}
return 0;
}
选出几个作为对照如下表。其中最右边的是上面函数的输出值,中间是参考的标准值。
数据 | 参考值 | 函数运算结果 |
1155.0f | 10.1736774445 | 10.1998583155 |
4.0f | 2.0000000000 | 2.0719286280 |
0.05f | -4.3219280243 | -4.3280713482 |
可以看到,数据在较小的值时,该算法会更精确。对(0, 1]范围内,以0.01为步长进行测试,该算法的误差平方和的均值大约为0.000934。因而该算法具有一定的实用性,可进行小范围的对数运算。
第一次写博客呢!不足的地方希望大家多多谅解,更希望稍花几秒,指出错误。