有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

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

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

然而,几年后出现了新的需求,对于某些罕见的场景,精度非常重要。因此,在这种情况下,我需要取一个价格(用double表示)、一个基数(也用double表示),然后将价格四舍五入到该基数的最近倍数,并再次将结果存储在double

在十进制形式中,这很简单:result = roundDownToBase(price + base*0.5, base)

我理解,天真地使用double执行上述公式将导致精度问题。我也明白一个正确的解决方法是在计算过程中将所有内容转换为BigDecimal

我的问题是,我如何系统地(单元)测试BigDecimal版本与double版本没有相同的精度问题?我可以随机选择一些值并断言结果,但鉴于输入的范围是无限的,这似乎并没有给我太多信心。或者,是否有一种方法可以在单元测试中系统地选取一些代表性的值,并对代码质量产生相当高的置信度

附:我的代码:

    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) 个答案

  1. # 1 楼答案

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