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

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

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

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位浮点数的东西,然后返回 – 例如。

不是浮点钻头的专家,我不能说结果浮点数是否有效(或需要规范化)


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

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

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

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

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

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