在减去双打时舍入问题

时间:2014-07-03 06:15:26

标签: java numeric

这是我的代码。

led.cost=led.cost-((Ledger)mdisellList.get(ms)).cost;

led.cost的初始值为4119.7,mdisellList.cost为172.485。两者都是双数据类型。

我在调试时看到了那些变量中的值(在.7或.485之后没有小数)。在此之前没有完成任何舍入。从4119.7中减去172.485时,结果为3947.2149999997而不是3947.215。

我想要3947.215而不是3947.2149999997。

4 个答案:

答案 0 :(得分:2)

不幸的是,在这些情况下,必须使用 BigDecimal 而不是double

双打是(负)2的幂(位!)的总和,这是十进制表示,如0.10只能近似:1/16 + 1/32 + ....计算偏差时,放大并变得可见。

要使用双打,人们将不得不使用格式化输出,DecimalFormat,(对于使用小数逗号和千位分隔符的语言环境来说,这是一件好事)。但是人们还需要不断地解决问题。并且考虑到税收和其他法律,有时会达到6位小数等等。

BigDecimal是一个不可变的值类型。它需要设置比例/精度,并且具有笨拙的addsubtractmultiply方法。

new BigDecimal("0.10"); // Works perfectly.
new BigDecimal(0.10); // Should not be used, looses precision 2,
                      // and has epsilon error.

然后是数据库方面。根据数据库系统, DOUBLE 可能优先选择 DECIMALS

(第三种选择是使用美分,long,但这也是间接的。)

答案 1 :(得分:0)

FINE!精细!同伴压力是双倍的。

如果你知道如何处理Java中的双打,或者你的项目要求不需要金融数学,那么在Java中使用双打就没问题。

但是,如果您不能确定浮点是如何工作的,请远离双打或受到诸如

之类的琐碎事情的伤害
System.out.println(0.01 + 5.02);

如果您不知道如何处理双打,那么更好的选择是坚持专门为此目的而设计的库,例如

http://en.wikipedia.org/wiki/Bignum
http://www.apfloat.org/
http://jscience.org/
java.math中。*。

答案 2 :(得分:0)

您可以将金额转换为较小的货币单位。手段 1欧元= 100美分。如果您有0.01欧元,则将其设为1美分并执行计算并使用BigDecimal和舍入模式将它们转换回欧元。

http://martinfowler.com/eaaCatalog/money.html

答案 3 :(得分:-2)

回答答案。

例如:

double valToRound = 172.485 - 4119.7;   
DecimalFormat df = new DecimalFormat("#.###");
System.out.println(df.format(valToRound));

结果:-3947.215