Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/313.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 执行涉及非终止大小数的算术_Java_Precision_Bigdecimal - Fatal编程技术网

Java 执行涉及非终止大小数的算术

Java 执行涉及非终止大小数的算术,java,precision,bigdecimal,Java,Precision,Bigdecimal,当除法一个BigDecimal时,结果可能是非终止的。因此,必须提供MathContext或RoundingMode/scale作为除法操作的一部分。但是,根据算术运算的顺序,精度损失可能会导致差异 当使用大小数时,如何避免由于精度损失(如下图所示)而产生的差异?我很想知道其他人是如何处理这类问题的 例如: 在上面的示例中,根据操作顺序,结果会发生变化 在测试时遇到这个示例之前,我从来没有考虑过BigDecimal操作的顺序是一个问题。现在,我左右为难:这是浮点算术的一个常见问题,不管是二进制还

当除法一个BigDecimal时,结果可能是非终止的。因此,必须提供MathContext或RoundingMode/scale作为除法操作的一部分。但是,根据算术运算的顺序,精度损失可能会导致差异

当使用大小数时,如何避免由于精度损失(如下图所示)而产生的差异?我很想知道其他人是如何处理这类问题的

例如:

在上面的示例中,根据操作顺序,结果会发生变化


在测试时遇到这个示例之前,我从来没有考虑过BigDecimal操作的顺序是一个问题。现在,我左右为难:

这是浮点算术的一个常见问题,不管是二进制还是十进制:除法可能是不精确的。所以当你必须做乘法和除法时,如果你先做除法,结果是不一致的,当你以后做乘法的时候,你会把第一个结果的误差乘以

在您的示例中,精确的结果是182.125,它正好位于要四舍五入到182.13的边界中。首先进行除法时,29.14/12的精确结果是2.428333

对于16位小数64,四舍五入为2.428333333,再乘以75,得到182.12499999997,四舍五入为182.12

那么,我们可以在这里做些什么:

如果没有溢出风险,则先进行乘法运算,最后进行除法运算。例如,对于a/b*c/d,您应该计算a*c/b*d 使用小数时,请尝试添加一个精度数字。在这里,您应该使用3位十进制数字的精度,因为初始数字是2位1。两种情况下的结果都是182.125
但无论如何,一旦没有精确的结果,就有可能出现舍入误差,这是浮点计算固有的。

BigDecimal没有精度损失,不确定数是那些这样的除法不能精确,并且以接近结果的周期结束的数字,比如1/3,结果是0.333333…我认为一个好的方法不是将结果四舍五入,而是简单地在some@MarcosVasconcelos问题是你不能用biginger.divide来获得精确的值,例如1/3。您必须指定截止位置,这会导致不可避免的精度损失。我不认为我们没有解决此类问题的工具,但发现多进制而不是除法不会产生此类错误:BigDecimal o=new BigDecimal 2;BigDecimal t=新的BigDecimal0.3333;BigDecimalT2=新的BigDecimal3;/*System.out.printlno.dividet2;*///RuntimeException System.out.printlno.multiplyt;//将分割的精度设置为比最终的精度高5-6位数。我原以为还需要更多的数字,但结果是5-6位数一般就足够了。最后,缩小到所需的精度。请注意,只有除法是一个问题。或者简单地使用更高的精度,并在末尾四舍五入到小数64。当然,如果可能的话,在除法之前一定要做乘法/加法/减法,正如你所说的,但是更高的精度会有很大帮助。甚至可以用简单的泰勒级数计算正弦或余弦。是的,我知道有更好的方法。谢谢!你能解释一下你的分区方法吗?如果我对所有数字都使用3的精度,那么一阶运算的结果是182.100,或者简单地使用更高的精度并四舍五入到小数64,这是一种有趣的方法。可以在除法中使用小数128,然后四舍五入到小数64,然后四舍五入到2位小数:v1.dividev2,MathContext.DECIMAL128.multiplyv3,MathContext.DECIMAL64.setScale2,RoundingMode.HALF_UP。这个问题仍然存在,但它大大降低了发生的几率。
BigDecimal v1 = new BigDecimal("29.14");
BigDecimal v2 = new BigDecimal("12");
BigDecimal v3 = new BigDecimal("75");
System.out.println(v1.divide(v2, MathContext.DECIMAL64).multiply(v3).setScale(2, RoundingMode.HALF_UP));
// Prints: 182.12
System.out.println(v1.multiply(v3).divide(v2, MathContext.DECIMAL64).setScale(2, RoundingMode.HALF_UP));
// Prints: 182.13