【问题标题】:BigDecimal add function display value not correctBigDecimal 添加函数显示值不正确
【发布时间】:2021-04-07 07:03:04
【问题描述】:

我有以下代码:

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。 请建议我在这里缺少什么以获得正确的数量?

【问题讨论】:

  • 真的需要AtomicReference才能获得效果吗?
  • 由于功能性 for 循环,我必须使用 AtomicReference
  • 您认为new MathContext(3) 是什么意思,您为什么这么认为? --- if 表示结果的精度为 3,即只有 3 位精度。 8024 减少到 3 位精度为 8020!!!
  • @user1999453 关于循环的建议: 使用普通循环:for (BigDecimal value : list) { totalAmount = totalAmount.add(value); } 其中变量定义为BigDecimal totalAmount = BigDecimal.ZERO;
  • 我的意思是:new BigDecimal(BigInteger.ZERO, new MathContext(3)).add(new BigDecimal(8024), new MathContext(3)).add(new BigDecimal(8024), new MathContext(3)) 将产生完全相同的结果。您的问题通过显示不必要的代码来混淆真正的问题。请将您的代码缩减到最低限度。

标签: java bigdecimal


【解决方案1】:

您似乎缺少两件事:

  1. 对于值:在相加时使用new MathContext(3) 会使值四舍五入为三位。首先添加 8024,然后将总和 8024 四舍五入为 8020。除前三位数字之外的所有内容都设置为 0,向上或向下舍入。然后再次加上 8024,总和 16044 四舍五入为 16000。
  2. 对于输出格式:当您打印BigDecimal 时,您(隐式或显式)调用它的toString 方法。这种方法经常产生你得到的科学记数法。确切的规则在文档中,请参阅底部的链接。如果您想确保控制BigDecimal 的格式,请使用DecimalFormat
  3. 在此示例中与您不需要的输出无关:您在添加时滥用AtomicReference,首先执行get(),然后执行set()。在多线程环境中(这是AtomicReference 有意义的地方),不同的线程可能会在这两个调用之间执行set() 或其他操作,但是当您执行set() 时,结果会丢失。相反,您应该使用AtomicReferenceaccumulateAndGet(或getAndAccumulate)方法。

我也不明白你为什么要以如此复杂的方式做事。这种更简单的方法可以满足您的要求:

    List<BigDecimal> list = List.of(new BigDecimal("8024"), new BigDecimal("8024"));
    
    BigDecimal totalAmount = BigDecimal.ZERO;
    for (BigDecimal value : list) {
        totalAmount = totalAmount.add(value);
    }
    System.out.println(totalAmount);

输出是:

16048

与其他答案中的代码类似。

编辑:作为一个好习惯,我将字符串文字传递给new BigDecimal()。虽然传递整数文字(例如 8024)本身没有问题,但传递双精度文字(例如 8024.1)通常意味着不准确。传递一个字符串总是会给你一个BigDecimsl,它的值与字符串完全相同。

文档链接

【讨论】:

  • 也许再补充一点:在这里传递整数文字是可行的,但可能是一个坏习惯,因为通过引入floating-point inaccuracy 可能会失败传递浮点/双精度文字。最好将输入作为字符串传递给BigDecimal
【解决方案2】:

BigDecimal 及其add() 方法将产生所需的结果。这里不需要使用 lambda 表达式。下面的代码演示了相同的内容。这也是干净的代码。

public static void main(String[] args) {
        
        List<BigDecimal> list = new ArrayList<BigDecimal>();
        
        list.add(new BigDecimal(8024));
        list.add(new BigDecimal(8024));
        
        BigDecimal total = BigDecimal.ZERO;
        
        for(BigDecimal element : list)
            total = total.add(element);
        
        System.out.print("Sum : " + total);
}

看到这个code run live at IdeOne.com

总和:16048

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-30
    • 2019-05-10
    • 2017-05-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多