是否必须使用BigDecimal来计算货币(Java)?

时间:2014-01-31 11:55:35

标签: java

PC是否有可能错误地添加2个十进制浮点数?

0.13 + 0.21 =0.340000000004

如果我们人类添加这2个数字,那么我们将不会有任何额外的分数错误吗?因为它不是逻辑,但计算机可以。

这台计算机有问题吗?

如何正确使用Java中的BigDecimal?

3 个答案:

答案 0 :(得分:3)

这不是强制性的,但至少有四个原因是好的做法:

  1. 货币总额可以任意增长(假设您为银行工作,希望系统在溢出时疯狂)。虽然十亿美元可能看起来很大,但考虑到一些货币,十亿甚至万亿可能不会那么多。
  2. 由于浮点近似,浮点数会受到侵蚀。仍然在银行示例中,您想要在任何交易中窃取或赠送美分,并且您希望银行帐户为空,不包含1e-37$
  3. 浮点数的精度有限。虽然这对于大多数应用程序来说都是可以的,但在处理货币时,您希望跟踪所有内容,从数十亿到美分。
  4. 浮动数字在处理货币时具有无意义的状态:客户存入NaN美元是什么意思?

答案 1 :(得分:1)

浮点运算长期以来一直是个问题。这就是鼓励使用BigDecimal的原因。关于如何正确使用它的问题,我有一个简单的例子可以帮助您了解BigDecimalMathContext一起使用的方式。

BigDecimal bd1 = new BigDecimal(0.13); // double value to BigDecimal
BigDecimal bd2 = new BigDecimal("0.21"); // String value to BigDecimal

MathContext mc = new MathContext(3, RoundingMode.HALF_EVEN); // first arg is the precision and the second is the RoundingMode.

BigDecimal bd3 = bd1.add(bd2, mc); // perform the addition with the context

System.out.println(bd3); // prints 0.340

答案 2 :(得分:0)

因为转换为二进制不均匀。当使用十进制系统

时,与1/3相同的部分变为0.33333333

浮点数标准称为IEEE 754,使用32位

这32位由以下部分组成

  • sign = 1 bit(0 = + ,, 1 = - )
  • 指数= 8位
  • 尾数= 23位

您可以通过访问

来查看

http://www.binaryconvert.com/result_float.html?decimal=048046051052

因此当将0.34(作为示例)转换为二进制时,它变为

 00111110 10101110 00010100 01111011

当计算机将其转换回来时,十进制fomrat中的结果不完全相同:

 00111110 10101110 00010100 01111011

 3.400000035762786865234375E-1