【问题标题】:Decimal Precision Issue | Big Decimal小数精度问题 |大十进制
【发布时间】:2016-03-10 15:34:10
【问题描述】:

1.

    BigDecimal ap = new BigDecimal(170.8999999999998,   MathContext.DECIMAL64).setScale(2, BigDecimal.ROUND_FLOOR);

结果:1​​70.89(必需:170.89)

2.

    BigDecimal ap = new BigDecimal(170.89999999999998, MathContext.DECIMAL64).setScale(2, BigDecimal.ROUND_FLOOR); (1 Extra 9 in value)

结果:1​​70.90(必需:170.89)

3.

    BigDecimal ap = new BigDecimal(2401.99).setScale(2, BigDecimal.ROUND_FLOOR);

结果:2401.98(必填:2401.99)

如何在不四舍五入的情况下从值中获得小数点后 2 位。

P.S : 我不想将值转换为字符串。

【问题讨论】:

  • 将数字放在引号中,以便将其字符串表示形式传递给 BigDecimal。目前您使用的是双字面值,在编译期间会产生舍入错误。

标签: java bigdecimal


【解决方案1】:

2401.99double literal,实际值略低于该值。

改用String 中的BigDecimal 构造函数。

【讨论】:

  • 所以2401.99实际上类似于2401.9888888888888887,而170.89999999999998实际上类似于170.90000000000000003
  • 最接近 2401.99 的双精度是 2401.989999999999781721271574497222900390625,最接近 170.89999999999998 的双精度是 170.89999999999926747626322455。部分问题是使用 ROUND_FLOOR,而不是例如ROUND_HALF_EVEN,但真正的解决方法是避免转换为双倍。
  • @P45Imminent 实际上,我将这些值作为 double 类型的函数的参数,并将其转换为 BigDecimal 以进行一些财务计算。我不想在添加或减去其他值时出现精度问题。有没有办法做到这一点而不将其转换为 String ?
  • @ABJK 你在做什么已经错了。如果您正在执行任何类型的财务计算,则您的值必须从不double 类型。让它在任何时候通过double 会使您的代码损坏。
  • @LouisWasserman 我知道,但假设这是“遗留”问题,我必须自己处理。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-14
  • 2013-06-21
相关资源
最近更新 更多