如何对“无精度误差”的数值计算进行单元测试?

时间:2016-10-11 09:40:31

标签: java unit-testing testing double precision

我们有一个用Java编写的大型系统,在大多数情况下,精度并不重要。因此,我们将所有数字存储为双倍。

然而,几年后出现了新的要求,并且对于某些罕见的情况,精确度非常重要。所以我遇到这种情况,我需要定价(在double中表示),一个基数(也在double中表示),并将价格四舍五入到该基数的最接近的倍数,并将结果再次存储在double

以十进制形式,这是微不足道的:result = roundDownToBase(price + base*0.5, base)

据我所知,用双重执行上述公式会导致精确度问题。我也理解一个正确的解决方法是在计算过程中将所有内容转换为BigDecimal。

我的问题是,我如何系统地(单元)测试BigDecimal版本不具有双版本具有的相同精度问题?我可以随机选择几个值并断言结果,但这似乎并没有给我太多的信心,因为输入的宇宙是无限的。或者,有没有办法在单元测试中系统地选择一些有代表性的值,并对代码质量产生相当高的置信度?

P.S。我的代码:

    public static double roundToNear(double price, double base) {
        BigDecimal value = BigDecimal.valueOf(price);
        BigDecimal baseValue = BigDecimal.valueOf(base);
        BigDecimal two = BigDecimal.valueOf(2);
        BigDecimal halfUp = value.add(baseValue.divide(two));
        return roundDownToBase(halfUp.doubleValue(), base);
    }

    public static double roundDownToBase(double value, double base) {
        BigDecimal val1 = BigDecimal.valueOf(value);
        BigDecimal val2 = BigDecimal.valueOf(base);
        BigDecimal remainder = val1.remainder(val2);
        return MathUtil.isZeroOrNaN(remainder.doubleValue()) ? value:val1.subtract(remainder).doubleValue();
    }

1 个答案:

答案 0 :(得分:0)

我认为在这种情况下你不能测试这些方法,因为它们是平台方法,根据我的经验,单元测试是针对你编写的代码,例如,如果你认为roundDownToBase(10.01,10.02)应该返回例如5那么wouuld将是一个有效的测试,否则你不能测试Double,因为这是平台功能