我将简要介绍一下我的实际情况:
让我们说我必须用Java实现一些代码来计算Weighted arithmetic mean。我得到两个浮点值数组(表示为双精度数),每个都有相同的长度,第一个包含值,第二个包含各自的权重。
我们还说我做了一些实现,它返回一个表示输入值的加权算术平均值的浮点值(也是一个double):
public static double calculateWeightedArithmeticMean(double[] values,
double[] weights) {
if(values.length != weights.length) {
throw new IllegalArgumentException();
}
if(values.length == 0) {
return 0;
}
if(values.length == 1) {
return new BigDecimal(values[0]).setScale(1, RoundingMode.HALF_UP).
doubleValue();
}
BigDecimal dividend = BigDecimal.ZERO;
BigDecimal divisor = BigDecimal.ZERO;
for(int i = 0; i < values.length; i++) {
dividend = dividend.add(new BigDecimal(values[i]).
multiply(new BigDecimal(weights[i])));
divisor = divisor.add(new BigDecimal(weights[i]));
}
if(dividend.compareTo(BigDecimal.ZERO) == 0) {
return 0d;
}
return dividend.divide(divisor, 1, RoundingMode.HALF_UP).doubleValue();
}
我写了一个单元测试,传递了几个值(比如,3个值+3个权重)。我首先手动计算他们的加权算术平均值(使用计算器),然后编写一个单元测试,检查我的代码是否返回该值。
我认为,由于舍入误差,这种测试与使用的数值明显较大的情况无关。也许我实现的代码适用于3个值+3个权重(对于给定的精度),因为舍入误差小于这种情况下的精度,但是舍入误差变得更大很可能超过1000个值+ 1000个权重的所需精度。
我的问题是:
答案 0 :(得分:1)
在编写单元测试时,你总是要放弃某个地方。当你确信你已经足够了解时,诀窍就是放弃: - )
在您的情况下,一些简单的测试用例是:
BigDecimal
输入数组)来计算所选输入的误差范围比较结果时,使用assertEquals(double, double, double)
,其中前两个是要比较的值,最后一个是精度(逗号后3位数的1e-3
)。
最后,您需要使用该算法并查看其行为方式。当您发现问题时,请为此特定情况添加测试用例。
答案 1 :(得分:1)
是的,你应该。测试(应该)总是涉及边界值。
您可以提供一个epsilon边界,断言答案是(大致)正确的。