最近因为某一些原因,需要要求高速计算一下常用对数的值。但是自然对数的快速算法和常用对数的快速算法都没想到......只得去找那个以2为底的对数值的快速运算方法了,由于精度要求不高(大约0.1即可),固可以尝试这种方案。
在内存中,float类型是这样存放的:
符号(1)+[指数位+127](7)+底数[23使用,占24],那么换句话说,当直接转换的时候,高位就要变成符号位,然呢,就是低位的处理了:
// x是输入的值
long *a;
float o;
a = (long*)&x;
o = (float)*a;
当上面的代码运行的时候,输出的o的值大约是满足下面这个式子的:
其中σ是一个无限小的数据,经过推倒值大约是0.0450466,但是这个只是理论。实际上,我发现这个值是在0.7几,数据才精确。自然的,由于上面的式子中出现了log2(x),因此可以借助这个方法计算2为底的对数值:
#define POW223 8388608.0f // 2^23
float __log2(float x)
{
long *a;
float o;
a = (long*)&x; // 强制的位转换
o = (float)*a;
o = o - POW223 * 126.92807138f; // 127.0f - sigem, ???实际证明那个0.04几的值误差非常大....
o = o / POW223;
return o;
}
在运行中,我分别测试了1155.0f, 4.0f, 0.05f这三个数,其中最右边的是上面函数的输出值,中间是参考的标准值
数据 | 参考值 | 函数运算结果 |
1155.0f | 10.1736774445 | 10.1998596191 |
4.0f | 2.0000000000 | 2.0719299316 |
0.05f | -4.3219280243 | -4.3280715942 |
第一次写博客呢!不足的地方希望大家多多谅解,更希望稍花几秒,指出错误