我有以下代码:
AtomicReference<BigDecimal> totalAmount = new AtomicReference<>(new BigDecimal(BigInteger.ZERO, new MathContext(3)));
List<BigDecimal> list = new ArrayList<BigDecimal>();
list.add(new BigDecimal(8024));
list.add(new BigDecimal(8024));
list.forEach(value -> {
totalAmount.set(totalAmount.get().add(value, new MathContext(3)));
});
基本上当我运行上述代码时,总金额的总和应该是 16048
但实际上是1.60e+4。请告诉我我在这里缺少什么来得到正确的数额?
2条答案
按热度按时间xxslljrj1#
你似乎错过了两件事:
对于值:使用
new MathContext(3)
加法时,使值四舍五入为三位数。首先你加8024,和8024,四舍五入到8020。前三位以外的所有数字都设置为0,向上或向下舍入。然后再加8024,和16044,四舍五入到16000。对于输出格式:打印
BigDecimal
,您正在(隐式或显式)调用toString
方法。这种方法经常产生你得到的科学符号。确切的规则在文档中,请参阅底部的链接。如果您想确保控制BigDecimal
,使用DecimalFormat
.与本例中不需要的输出无关:您使用不当
AtomicReference
当你第一次做get()
然后是一个set()
. 在多线程环境中(这是AtomicReference
有任何意义)一个不同的线程可以做一个set()
或者在这两个调用之间执行其他操作,但这样做的结果会丢失set()
. 相反,你应该使用accumulateAndGet
(或getAndAccumulate
)方法AtomicReference
.我也不明白你为什么这么复杂。这种简单的方法可以满足您的要求:
输出为:
16048
这与另一个答案中的代码相似。
编辑:作为一个好习惯,我将字符串文字传递给
new BigDecimal()
. 虽然传递一个整数文本(如8024)本身没有问题,但传递一个双精度文本(如8024.1)通常意味着不准确。传递一根线总会给你一个答案BigDecimsl
与字符串保持完全相同的值。文档链接
BigDecimal.toString()
DecimalFormatAtomicReference.accumulateAndGet()
new9mtju2#
BigDecimal
以及它的add()
方法将产生所需的结果。这里不需要使用lambda表达式。下面的代码演示了相同的情况。这也是干净的代码。请在ideone.com上查看此代码的实时运行。
总数:16048