Java BigDecimal:使用setScale进行半舍五入

Java BigDecimal:使用setScale进行半舍五入,java,bigdecimal,Java,Bigdecimal,我们有以下代码: BigDecimal net = price .divide(taxCumulative, RoundingMode.HALF_UP) .setScale(2, BigDecimal.ROUND_UP); 我们正在对此进行单元测试,并根据是否在测试类上使用@Transactional得到不同的结果 我只是想知道,我们是否应该将HALF_UP的应用与setScale一起考虑,还是在它之前考虑 例如: 说: 价格=4.00 税收累计=1.20 您是否希望计算结果如下: a) 4

我们有以下代码:

BigDecimal net = price
.divide(taxCumulative, RoundingMode.HALF_UP)
.setScale(2, BigDecimal.ROUND_UP); 
我们正在对此进行单元测试,并根据是否在测试类上使用
@Transactional
得到不同的结果

我只是想知道,我们是否应该将
HALF_UP
的应用与
setScale
一起考虑,还是在它之前考虑

例如:

说:

价格=4.00

税收累计=1.20

您是否希望计算结果如下:

a)
4.00/1.20=3.33333…-->对半-->3-->设置刻度-->3

b)
4.00/1.20=3.33333…-->设置刻度为2-->3.33的半刻度

正如我所说,我们对这段代码进行了单元测试,当我们使用
@Transactional
与否时,它们的行为会有所不同。因此,我们无法得出结论。在现实世界中,结果是b。但是,一个好的选择也是有意义的

有什么想法吗

更新

根据@Mark的建议,我在spring上下文之外创建了一个测试。(但我想没有办法像codepen那样在线分享)

因此,正如@gtgaxiola所指出的,字符串构造函数起了作用

至于使用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

检查上的构造函数注释

1.-此构造函数的结果可能有些不可预测。可以假设,在Java中编写新的BigDecimal(0.1)会创建一个完全等于0.1的BigDecimal(无标度值1,标度为1),但实际上等于0.10000000000000055115123125782702118158340451015625。这是因为0.1不能精确地表示为双精度(或者,就此而言,表示为任何有限长度的二进制分数)。因此,传递给构造函数的值并不完全等于0.1,尽管如此

2.-另一方面,字符串构造函数是完全可预测的:编写新的BigDecimal(“0.1”)会创建一个完全等于0.1的BigDecimal,正如人们所期望的那样。因此,通常建议优先使用字符串构造函数而不是此构造函数

3.-当必须将double用作BigDecimal的源时,请注意此构造函数提供精确转换;它不会给出与使用double.toString(double)方法然后使用BigDecimal(String)构造函数将double转换为字符串相同的结果。要获得该结果,请使用static valueOf(double)方法


你应该包括一个。如果我启动
BigDecimal(4.00)
BigDecimal(1.20)
,则案例a和案例bI get
a之间的价格听起来像是“4”或“4.00”。我得到
b
如果启动
BigDecimal(“4.00”)
BigDecimal(“1.20”)
也要注意,这不是一个“应该期望在设置刻度时或之前考虑应用半刻度”的问题。舍入应用于除法,也适用于应用
setScale
时。四舍五入到结果3是因为除法时应用的规则和当前的
price
比例。看见
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