java - 使用 MathContext 调用时,BigDecimal.divide() 会产生额外的精度数字

标签 java bigdecimal arbitrary-precision precision

给定简单的程序

import java.math.*;
import static java.math.BigDecimal.ONE;
import static java.lang.System.out;

public static void main(String[] args) {
    StringBuffer ruler = new StringBuffer("  ");
    for (int i = 0; i < 5; i++) {
         ruler.append("1234567890");
    }

    out.println(ONE.divide(new BigDecimal(47), 50, RoundingMode.HALF_UP));
    out.println(ONE.divide(new BigDecimal(47), new MathContext(50, RoundingMode.HALF_UP)));
    out.println(ruler);
    out.println(ONE.divide(new BigDecimal(6), 5, RoundingMode.HALF_UP));
    out.println(ONE.divide(new BigDecimal(6), new MathContext(5, RoundingMode.HALF_UP)));
}

这是输出:

0.02127659574468085106382978723404255319148936170213
0.021276595744680851063829787234042553191489361702128
  12345678901234567890123456789012345678901234567890
0.16667
0.16667

我希望第二行输出与第一行相同。这是一个错误,还是我误解了 BigDecimal 文档?

JVM 版本:

$ java -version
java version "1.7.0_45"
Java(TM) SE Runtime Environment (build 1.7.0_45-b18)
Java HotSpot(TM) 64-Bit Server VM (build 24.45-b08, mixed mode)

最佳答案

您混淆了小数位数(小数位数总数)和精度(有效位数)。对于 -1 和 1 之间的数字,精度 不计算小数点和非零小数位之间的任何零,但比例 计算。

BigDecimal.divide 的第二个参数是一个scale。因此,您的第一个输出得到 50 位小数。

MathContext 构造函数的参数是一个精度。因此,对于您的第二个输出,您将获得 50 个有效的小数位,以及小数点和 2 之间的一个额外零。

  First decimal place (start counting scale from here)
  ↓
0.02127659574468085106382978723
   ↑
   First significant digit (start counting precision from here)

关于java - 使用 MathContext 调用时,BigDecimal.divide() 会产生额外的精度数字,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23505255/

相关文章:

java - 将两个大数相加作为两个数组

java - 确定字符串是否为数字并在Java中转换?

Javascript 错误地更改了简单乘法的结果。我该如何解决?

c - Visual Studio 2010 的多精度

precision - CPLEX 中没有输入变化很小的解

Java:在不同的文件夹中导入我自己的包

java - 如果条件不适用于相关实体

java - 从同一列的组件菜单中删除 JTable 列时出错

java - 关于 BigDecimal ROUND_DOWN 的问题

assembly - AVX VMOVDQA 比两个 SSE MOVDQA 慢?