我们有以下代码:
BigDecimal net = price
.divide(taxCumulative, RoundingMode.HALF_UP)
.setScale(2, BigDecimal.ROUND_UP);
我们正在对此进行单元测试,并根据是否在测试类上使用@Transactional
来获得不同的结果。
我只是想知道我们是否应该将HALF_UP
的应用与setScale
一起或在其之前考虑。
例如:
说:
价格= 4.00
taxCumulative = 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。
答案 0 :(得分:3)
它似乎会受到影响,具体取决于您构建BigDecimal
检查public BigDecimal(double val)上的构造函数注释
1。-此构造函数的结果可能无法预测。有人可能会假设用Java编写新的BigDecimal(0.1)会创建一个BigDecimal,它精确地等于0.1(未缩放的值1,小数位数为1),但实际上等于0.1000000000000000055511151231257827021181583404541015625。这是因为0.1无法精确表示为双精度(或就此而言,表示为任何有限长度的二进制分数)。因此,尽管出现,传递给构造函数的值并不完全等于0.1。
2。-另一方面,String构造函数是完全可预测的:就像期望的那样,编写新的BigDecimal(“ 0.1”)会创建一个完全等于0.1的BigDecimal。因此,通常建议优先使用String构造函数。
3.-当必须将double用作BigDecimal的源时,请注意此构造函数提供了精确的转换;它与使用Double.toString(double)方法然后使用BigDecimal(String)构造函数将double转换为String的结果不同。要获得该结果,请使用静态valueOf(double)方法。