浮点数的表示

IEEE 754规定浮点数值表示:

x = s * m * 2^e

其中s为符号,m[1, 2)中的小数量值,e是指数。不计符号,于是:

log(2, x) = log(2, m) + e

近似地:

log(2, x) = e

编码后的浮点数表示为(S, E(K), M(N))三元组,其中
符号:s = (-1)*S
量值:
m = 1 + M / 2^N
指数:e = E - 2^(K - 1) + 1

对于单精度类型floatK = 8, N = 23,总共占据32比特。

例如,对于编码后双字:0x3dcccccd
分解为
S = 0(2) = 0
E = 01111011(2) = 123
M = 10011001100110011001101(2) = 5033165

因此
s = 1
m = 1.6
e = -4

解码得到f = 0.1

利用浮点数的这一特征,可以做出一种log2函数实现参考(以下代码均见于参考文献):

令:
y = M / 2^N
u = E + y
b = 2^(K - 1) - 1

log2(x) = e + log2(m)
        = (E - 2^(K - 1) + 1) + log2(1 + M / 2^N)
        = u - b + (log2(1 + y) - y)

其中log2(1 + y) - y可以用二次曲线近似:
log2(1 + y) - y ~= 0.346607 * (y - y^2)

由此log2可以实现为:

float mylog2 (float x)
{
    const float LogBodge = 0.346607f;
    float y;
    x = *(int *)&x;
    x *= 1.0f / (float)(1 << 23);    /* 形成定点构造 */
    x -= 127;

    y = x - floorf(x);
    y = (y - y * y) * LogBodge;
    return x + y;
}

而求幂函数则用相反的计算:
pow2(x) = pow2(floor(x) + decimal(x))
        = pow2(decimal(x)) * pow2(floor(x))
        = pow2(decimal(x)) * 2^(floor(x))

1 + M / 2^N = m = pow2(decimal(x))
E - 2^(K - 1) + 1 = e = floor(x)

于是
M = (pow2(decimal(x)) - 1) * 2^N
E = floor(x) + 2^(K - 1) - 1

定点构造
x - decimal(x) + pow2(decimal(x)) - 1

其中y = pow2(t) - t - 1的计算也用二次曲线近似
y = 0.33971 * (t^2 - t);

其实现为:

float mypow2 (float x)
{
    const float PowBodge = 0.33971f;
    float y = x - floorf(x);
    y = (y - y * y) * PowBodge;

    x += 127 - y;
    x *= (float)(1 << 23);
    *(int*)&x = (int)x;
    return x;
}

参考:
http://www.dctsystems.co.uk/Software/power.html

 

posted @ 2007-07-20 18:03  quanben  阅读(331)  评论(0编辑  收藏  举报