我们有以下代码:
BigDecimal net = price
.divide(taxCumulative, RoundingMode.HALF_UP)
.setScale(2, BigDecimal.ROUND_UP);
我们正在对此进行单元测试,并根据是否在测试类上使用事务性测试得到不同的结果。
我只想知道我们是否应该期望HALF_UP
的应用程序与setScale
一起考虑,还是在它之前考虑。
例如:
说:
价格=4.00
累计税收=1.20
您是否希望计算结果如下:
a) <代码>4.00/1.20=3.33333333--
或
b)<代码>4.00 / 1.20 = 3.33333333...--
正如我所说,我们对这段代码进行了单元测试,当我们有没有事务性代码时,它们的行为会有所不同。因此,我们无法得出结论。在现实世界中,结果是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所指出的,字符串构造函数起到了作用。
至于除法运算使用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
检查公共BigDecimal(double val)上的构造函数注释
1.-这个构造函数的结果可能有些不可预测。人们可能会假设在Java中编写新的BigDecimal(0.1)会创建一个正好等于0.1的BigDecimal(一个未缩放的值为1,刻度为1),但它实际上等于0.1000000000000000055511151231257827021181583404541015625。这是因为0.1不能完全表示为双精度(或者,就此而言,作为任何有限长度的二进制分数)。因此,传递给构造函数的值并不完全等于0.1,尽管看起来是这样。
2.-另一方面,字符串构造函数是完全可预测的:编写新的BigDecimal(“0.1”)会创建一个恰好等于0.1的BigDecimal,正如人们所期望的那样。因此,通常建议优先使用String构造函数而不是这个。
3.-当双精度必须用作BigDecimal的源时,请注意,此构造函数提供了精确的转换;它不会给出与使用Double.toString(双精度)方法将双精度转换为String然后使用BigDecimal(String)构造函数相同的结果。要获得该结果,请使用静态value Of(双精度)方法。
我将以下代码与java BigDecimal setScale方法结合使用,并使用半\u偶数舍入模式,得到以下结果。 结果:1.11 预计:1.12 由于距离5最近的偶数数字应该是2,因此我预期的结果是1.12。但结果是1.11。再一次, 结果:1.15 预期:1.14 因为5左边的偶数是4,所以我希望结果是1.14。对此有什么解释吗?
问题内容: 这两个电话有什么区别?(有没有?) 问题答案: 提到但没有直接解决的一个重要问题是 “精度” 和 “比例” 之间的区别以及它们在两个语句中的用法。 “精度” 是数字中有效数字的总数。 “比例” 是小数点右边的位数。 MathContext构造函数仅接受precision和RoundingMode作为参数,因此第一条语句中从未指定scale。 显然接受scale和RoundingMode
问题内容: 我将以下代码与具有Half_even舍入模式的Java BigDecimal setScale方法配合使用,并获得以下结果。 结果:1.11 预期值:1.12 由于最接近5的偶数应该是2,因此我期望的结果是1.12。但是结果是1.11。然后再次, 结果:1.15 预期值:1.14 因为5左边的偶数是4,所以我期望结果是1.14。有什么解释吗? 问题答案: 这是由浮点不精确(在您的输入值
描述 (Description) java.math.BigDecimal.setScale(int newScale)返回一个BigDecimal,其标度是指定值,其值在数值上等于此BigDecimal。 如果不可能,则抛出ArithmeticException。 此调用通常用于增加比例,在这种情况下,可以保证存在指定比例的BigDecimal和正确的值。 如果调用者知道BigDecimal在其
我正在这样做: 我得到了这个错误: java.lang.算术异常:非终止小数展开;没有精确可表示的小数结果。 我需要把setScale放在哪里? 谢谢
问题内容: 以下代码使用, 分别显示和。在我看来,它应该分别显示和,因为丢弃的小数部分左边的数字(在这种情况下为5)是 奇数 。在这种情况下, 并且在的情况下, 当丢弃的小数部分> = 0.5时执行(这是正确的),否则执行。 问题答案: 该行为在Javadoc中有很好的描述: 舍入模式向“最近的邻居”舍入, 除非两个邻居都等距,在这种情况下,向偶数邻居舍入 。 因此,给定数字4.5,当您调用它时,