我们有以下代码:
BigDecimal net = price
.divide(taxCumulative, RoundingMode.HALF_UP)
.setScale(2, BigDecimal.ROUND_UP);
我们正在对此进行单元测试,根据我们是否在测试类上使用
@Transactional
,结果有所不同。我只是想知道,在使用
setScale
之前还是之后,我们是否应该期望应用 HALF_UP
。例如:
假设:
价格 = 4.00
税累计 = 1.20
您会期望计算方式如下:
a)
4.00 / 1.20 = 3.33333333... --> HALF_UP --> 3 --> setScale --> 3
或者b)
4.00 / 1.20 = 3.33333333... --> HALF_UP with setScale 2 --> 3.33
正如我所说,我们针对这段代码进行了单元测试,并且在是否使用 @Transactional
时行为不同。因此我们不能得出结论。在现实世界中,结果是b。但是 a 也是有意义的。您有什么想法吗?
更新:
根据 @Mark 的建议,我创建了一个在 Spring 上下文之外的测试。(但我想没有办法在线分享它,就像 codepen 那样)。
package com.company;
import java.math.BigDecimal;
import java.math.RoundingMode;
public class Main {
public static void main(String[] args) {
BigDecimal price = new BigDecimal("4.00");
BigDecimal taxCumulative = new BigDecimal("1.20");
BigDecimal net = price.divide(taxCumulative, RoundingMode.HALF_UP).setScale(2, BigDecimal.ROUND_UP);
System.out.println("With String constructor, the net = " + net.toString());
// prints 3.33
price = new BigDecimal(4.00);
taxCumulative = new BigDecimal(1.20);
net = price.divide(taxCumulative, RoundingMode.HALF_UP).setScale(2, BigDecimal.ROUND_UP);
System.out.println("With doubles, the net = " + net.toString());
// prints 3.00
}
}
正如@gtgaxiola指出的那样,String构造函数是有区别的。
至于使用setScale进行除法操作的问题。我做了一些更多的测试:
price = new BigDecimal("4.000000");
taxCumulative = new BigDecimal("1.2000000");
net = price.divide(taxCumulative, RoundingMode.HALF_UP).setScale(2, BigDecimal.ROUND_UP);
// 3.34
price = new BigDecimal("4.000000");
taxCumulative = new BigDecimal("1.2000000");
net = price.divide(taxCumulative, RoundingMode.HALF_UP);
// 3.333333
price = new BigDecimal("4");
taxCumulative = new BigDecimal("1.2");
net = price.divide(taxCumulative, RoundingMode.HALF_UP);
// 3
因此,结果高度取决于字符串输入的精度,setScale是在除法产生结果后应用的。
BigDecimal(4.00)
和BigDecimal(1.20)
,那么我会得到a
。如果我初始化BigDecimal("4.00")
和BigDecimal("1.20")
,那么我会得到b
。 - gtgaxiola