我认为java.math.BigDecimal应该是™对使用十进制数执行无限精度算术的需要的答案。
考虑以下片段:
import java.math.BigDecimal;
//...
final BigDecimal one = BigDecimal.ONE;
final BigDecimal three = BigDecimal.valueOf(3);
final BigDecimal third = one.divide(three);
assert third.multiply(three).equals(one); // this should pass, right?我希望assert能够通过,但实际上执行甚至没有达到:one.divide(three)会导致抛出ArithmeticException!
Exception in thread "main" java.lang.ArithmeticException:
Non-terminating decimal expansion; no exact representable decimal result.
at java.math.BigDecimal.divide事实证明,这种行为已在API接口中显式地记录下来。
在
divide的情况下,精确商可以有一个无限长的十进制展开;例如,1除以3。如果商数有一个不终止的十进制展开,并且指定了返回精确结果的运算,则抛出一个ArithmeticException。否则,将返回除法的确切结果,与其他操作一样。
进一步浏览API,人们会发现,实际上存在着执行不精确划分的各种divide重载,即:
final BigDecimal third = one.divide(three, 33, RoundingMode.DOWN);
System.out.println(three.multiply(third));
// prints "0.999999999999999999999999999999999"当然,现在最明显的问题是“有什么意义??”。我认为当我们需要精确的算术时,例如在财务计算时,BigDecimal是解决问题的方法。如果我们甚至不能准确地实现divide,那么这又能有多大的用处呢?它实际上是通用的吗,还是只在一个非常利基的应用程序中有用,而幸运的是,您根本不需要使用divide?
如果这不是正确的答案,那么在财务计算中,我们能用什么来精确划分呢?(我的意思是,我没有金融专业,但他们仍然使用部门,对吧??)
发布于 2010-05-01 17:09:47
这个类是BigDecimal而不是BigFractional。从您的一些评论中,听起来您只是想抱怨没有在这个类中构建所有可能的数字处理算法。金融应用程序不需要无限的十进制精度;只是精确到所需的精确值(通常是0、2、4或5小数位)。
实际上,我已经处理过许多使用double的金融应用程序。我不喜欢它,但这就是它们的编写方式(也不是用Java编写的)。当存在汇率和单位换算时,就有可能出现四舍五入和瘀伤问题。BigDecimal消除了后者,但仍有前者用于除法。
发布于 2010-05-01 11:31:14
如果你想处理小数,而不是有理数,并且在最后的四舍五入(四舍五入)之前需要精确的算术(四舍五入),下面是一个小技巧。
你总是可以操纵你的公式,以便只有一个最后的除法。这样,你就不会在计算过程中失去精度,你就能得到正确的四舍五入的结果。例如
a/b + c等于
(a + bc) / b.发布于 2010-05-01 10:19:36
顺便说一句,我真的很感激从事金融软件工作的人的洞察力。我经常听到BigDecimal被提倡加倍
在财务报告中,我们使用标度=2和BigDecimal,因为报表中的所有打印值都必须导致可复制的结果。如果有人用一个简单的计算器来检查这个。
在瑞士,由于他们不再拥有1或2枚拉普硬币,所以他们的硬币的周转率为0.05。
https://stackoverflow.com/questions/2749375
复制相似问题