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