我正在为执行浮点数计算的代码编写测试。很可能,结果很少是准确的,我想在计算结果和预期结果之间设置一个容差。我已经验证了在实践中,使用双精度,在舍入最后两位有效小数后结果总是正确的,但是在舍入最后一位小数后通常是。我知道存储double
和float
的格式,以及舍入的两种主要方法(精确地通过BigDecimal
并通过乘法更快,{{1}和分裂)。由于尾数以二进制形式存储,是否有办法使用基数2而不是10来执行舍入?
只是清除最后3位几乎总能得到相同的结果,但如果我可以推动它而不是添加2'如果设置了第二个最小有效位,那么我可能会达到准确度极限。这很容易,我不知道如何处理溢出(当所有位52-1都被设置时)。
Java解决方案将是首选,但如果我理解的话,我可以将其中一个用于另一种语言。
编辑:
问题的一部分是我的代码在算术方面是通用的(依赖于math.round
类型类),我所做的是将答案中建议的舍入结合到一个新的数字类型中,该数字类型带有计算出的数字(在这种情况下为浮点)和舍入误差,基本上代表一个范围而不是一个点。然后我覆盖等于两个数字相等,如果它们的误差范围重叠(并且它们共享算术,即数字类型)。
答案 0 :(得分:7)
是的,舍入二进制数字比通过BigDecimal
更有意义,如果您不担心Double.MAX_VALUE
的小因素,可以非常有效地实现。
您可以使用Java(未经测试)中的以下序列舍入浮点double
值x
:
double t = 9 * x; // beware: this overflows if x is too close to Double.MAX_VALUE
double y = x - t + t;
在此序列之后,y
应包含舍入值。调整常量9
中两个设置位之间的距离,以调整四舍五入的位数。值3
四舍五入。值5
舍入两位。值17
将四位四舍五入,依此类推。
该指令序列归属于Veltkamp,通常用于“Dekker乘法”。 This page有一些参考资料。