BigDecimal的setScale和round方法

172

这两个调用有什么区别吗?(有吗?)

// 1.
new BigDecimal("3.53456").round(new MathContext(4, RoundingMode.HALF_UP));
// 2.
new BigDecimal("3.53456").setScale(4, RoundingMode.HALF_UP);

8
除下面已接受的答案之外,setScale()方法会创建一个新的BigDecimal对象。因为BigDecimal是不可变类。 - prash
11
@prash,“round”方法也会返回一个新的BigDecimal实例,因为正如你所说,这些实例是不可变的。 - daiscog
1
区别在于你几乎总是想要使用.setScale,而另一个则是学术命名法胜过普通人的令人分心的例子。 - MarkHu
2个回答

263

提到但没有直接讨论的一个重要点是"精度""标度"的区别,以及它们在这两个声明中的使用。 "精度"是数字中有效位数的总数。 "标度"是小数点右侧的数字位数。

MathContext构造函数只接受精度和RoundingMode作为参数,因此在第一个语句中永远不会指定标度。

setScale()显然接受标度和RoundingMode作为参数,但在第二个语句中永远不会指定精度。

如果将小数点向右移动一位,差异将变得清晰:

// 1.
new BigDecimal("35.3456").round(new MathContext(4, RoundingMode.HALF_UP));
//result = 35.35
// 2.
new BigDecimal("35.3456").setScale(4, RoundingMode.HALF_UP);
// result = 35.3456

49
“‘精度’指的是一个数字中有效数字的数量,而不是数字总位数。” “0.000042M”的精度为2。” - David J.
3
参见:"precision":数字计数从精确结果的最左侧非零数字开始。https://docs.oracle.com/javase/7/docs/api/java/math/BigDecimal.html - Eddy
如果“精度是有效数字的数量”,那么为什么0.0000009的精度为2?它应该是1。 - Sanchi Girotra
1
你的BigDecimal的值是如何设置的?你是如何输出该值的(使用String.format()可能会隐藏重要数字)? - dale peters
1
@SanchiGirotra 精度是“未缩放值中的数字数”。精度为2,未缩放值为90,比例为8时,结果为0.0000009。当精度为1,未缩放值为9,比例为7时,结果也是如此。 - daiscog
显示剩余2条评论

54

确实有很大的区别,这一点您应该牢记。 setScale实际上设置了您的数字的比例,而round则将数字四舍五入到指定的位数,但它“从精确结果的最左边数字开始”如jdk中所述。因此针对您的示例,结果是相同的,但请尝试0.0034。 这是我在博客上关于此的注释:

http://araklefeistel.blogspot.com/2011/06/javamathbigdecimal-difference-between.html


样本的结果不同://1为3.535,//2为3.5346。 - fall

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接