快速浮动量化,按精度缩放?

时间:2018-02-09 04:20:19

标签: c floating-point

由于浮点精度因较大值而减小,在某些情况下,根据其大小量化值可能很有用 - 而不是按绝对值进行量化。

一种天真的方法可能是检测精度并进行扩展:

float quantize(float value, float quantize_scale) {
    float factor = (nextafterf(fabsf(value)) - fabsf(value)) * quantize_scale;
    return floorf((value / factor) + 0.5f) * factor;
}

然而这似乎太重了。

相反,它应该可以掩盖浮动mantisa中的位 模拟类似于铸造到16位浮点数的东西,然后返回 - 例如。

不是浮点钻头的专家,我不能说结果浮点数是否有效(or need normalizing)

对于速度,当关于舍入的确切行为不重要时,量化浮点数的快速方法是什么,考虑其大小?

1 个答案:

答案 0 :(得分:1)

Veltkamp-Dekker分裂算法将浮点数分成高低部分。示例代码如下。

如果有效数字中有 s 位(IEEE 754 64位二进制中为53),则下面代码中的值Scale为2 b ,然后*x0收到x的高 s - b 位,并且*x1收到剩余的位,您可以丢弃(或从下面的代码中删除,因此永远不会计算)。如果在编译时知道 b ,例如常数43,则可以用适当的常量替换Scale,例如0x1p43。否则,你必须以某种方式产生2 b

这需要圆到最近的模式。 IEEE 754算术就足够了,但其他合理的算法也可以。它使关系变得均匀。

这假设x * (Scale + 1)没有溢出。必须以与分离值相同的精度评估操作。 (doubledoublefloatfloat,依此类推。如果编译器使用float评估double个表达式,则会中断。解决方法是将输入转换为支持的最宽浮点类型,执行该类型的拆分[相应调整Scale],然后转换回来。)

void Split(double *x0, double *x1, double x)
{
    double d = x * (Scale + 1);
    double t = d - x;
    *x0 = d - t;
    *x1 = x - *x0;
}