我以为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
则抛出an
。否则,将返回除法的精确结果,就像其他操作一样。
进一步浏览API,人们发现实际上divide
执行 不精确 划分的各种重载,即:
final BigDecimal third = one.divide(three, 33, RoundingMode.DOWN);
System.out.println(three.multiply(third));
// prints "0.999999999999999999999999999999999"
当然,现在显而易见的问题是“这有什么用呢?”。我认为这BigDecimal
是当我们需要 精确
算术(例如财务计算)时的解决方案。如果我们甚至无法divide
完全做到这一点,那么这有什么用呢?它实际上是为一般目的服务的吗,还是仅在您完全不需要的非常利基的应用程序中有用divide
?
如果这不是正确的答案,什么 CAN 我们使用的财务核算准确划分的?(我的意思是,我没有金融专业,但他们仍然使用部门划分,对吗?)。
如果这不是正确的答案,那么我们可以在财务计算中使用什么进行精确划分呢?(我的意思是,我没有金融专业,但他们仍然使用部门划分,对吗?)。
那时我在小学1年,他们告诉我,当您用1除以3时,您会得到0.33333 …即一个 重复的
小数。以十进制形式表示的数字除法不精确。事实上,对于任何固定的 基座 将存在不能表示级分(将一个整数由另一个的结果) 恰好
为一个有限精度浮点在于基点数。(数字将重复出现…)
当您进行涉及除法的财务计算时,您 必须 考虑如何处理重复部分。您可以将其向上或向下四舍五入,或者四舍五入到最接近的整数,或者其他一些东西,但是基本上您
不能 忘记这个问题。
BigDecimal Javadoc表示:
BigDecimal类为用户提供了对舍入行为的完全控制。如果未指定舍入模式并且无法表示确切结果,则会引发异常;否则,将抛出异常。否则,可以通过向运算提供适当的MathContext对象,以选定的精度和舍入模式进行计算。
换句话说, 您有责任 告诉BigDecimal如何进行舍入。
编辑 -针对OP的这些后续措施。
BigDecimal如何检测无限循环十进制?
它不会显式检测重复的十进制数。它只是检测到某些操作的结果无法使用指定的精度精确表示;例如,小数点后需要太多位数才能精确表示。
它必须跟踪并检测股息循环。它可能已经选择了另一种方式来处理,例如标记重复部分在哪里等。
我想BigDecimal
可以指定它精确地表示一个重复的十进制数。即作为一个BigRational
类。但是,这会使实现更加复杂,使用起来也更昂贵2。而且由于大多数人期望数字以十进制显示,因此在这一点上还会出现重复十进制的问题。
底线是,这种额外的复杂性和运行时成本对于的典型用例而言是不合适的BigDecimal
。这包括财务计算,其中会计惯例不允许您使用重复小数。
1-这是一所很棒的小学…
2-要么尝试消除除数和除数的公因子(计算上昂贵),要么让它们无限制地增长(空间使用成本高昂,并且为以后的操作计算上昂贵)。
这是我的XML文件: 我创建了两个类来解析它(Fields.java和Field.java): 和 但我有一个例外: 我不明白为什么会出现这种例外。例外情况如下: 我使用JDK 1.6_0.0.7。谢谢。
我正在使用一个相对较大的代码存储库,需要全部加载到Intellij中。最近Intellij挂起了很长时间( 冻结期间的Stacktrace:
不同的是,第一个列表包含5项,而第二个列表包含3项。使用的JVM是: 问题:为什么第二段代码不抛出java.util.concurrentModificationException?
我有以下POJO: 以及以下控制器: 问题在于,它不是生成错误DataFormatException,而是生成: 虽然如上所述,问题是正确的,但信息是错误的。那么,为了产生想要的错误而不是杰克逊产生的错误,我们能做些什么呢?
问题内容: 当我运行此代码时,我将抛出ConcurrentModificationException。 当我从列表中删除指定的元素时,列表似乎不知道其大小已更改。 我想知道这是否是集合和删除元素的常见问题? 问题答案: 我相信这是Iterator.remove()方法背后的目的,是能够在迭代时从集合中删除一个元素。 例如:
我在我的Web应用程序中使用引导日期时间选择器,由PHP/HTML5和JavaScript制作。我目前正在使用一个:http://tarruda.github.io/bootstrap-datetimepicker/ 当我没有时间使用控件时,它不工作。它只显示一个空白文本框。 我只想从日期时间选择器中删除时间。有什么解决办法吗?