java - 由于 BigDecimals 中的二进制表示形式导致数字不准确。我该如何解决它?

标签 java bigdecimal

我想编写一个将字符串转换为 BigDecimal 的解析器。 要求100%准确。 (嗯,我现在编程是为了好玩。所以我宁愿要求它......;-P)

所以我想出了这个程序:

public static BigDecimal parse(String term) {
    char[] termArray = term.toCharArray();

    BigDecimal val = new BigDecimal(0D);
    int decimal = 0;
    for(char c:termArray) {
        if(Character.isDigit(c)) {
            if(decimal == 0) {
                val = val.multiply(new BigDecimal(10D));
                val = val.add(new BigDecimal(Character.getNumericValue(c)));
            } else {
                val = val.add(new BigDecimal(Character.getNumericValue(c) * Math.pow(10, -1D * decimal)));
                decimal++;
            }
        }
        if(c == '.') {
            if(decimal != 0) {
                throw new IllegalArgumentException("There mustn't be multiple points in this number: " + term);
            } else {
                decimal++;
            }
        }
    }

    return val;
}

所以我尝试了:

parse("12.45").toString();

我预计它是12.45。相反,它是 12.45000000000000002498001805406602215953171253204345703125。我知道这可能是由于二进制表示的限制。但我该如何解决这个问题呢?

注意:我知道您可以使用new BigDecimal("12.45");。但这不是我的观点 - 我想自己写它,无论这可能有多愚蠢。

最佳答案

是的,这是由于二进制表示的限制。任何 10 的负幂都不能精确地表示为 double

要解决此问题,请将所有 double 算术替换为所有 BigDecimal 算术。

val = val.add(
    new BigDecimal(Character.getNumericValue(c)).divide(BigDecimal.TEN.pow(decimal)));

这样我得到12.45

关于java - 由于 BigDecimals 中的二进制表示形式导致数字不准确。我该如何解决它?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55752888/

相关文章:

java - 随机数计数器不工作

java - Java 中的继承——创建子类的对象也会调用父类(super class)的构造函数。为什么?

java - 仅使用 For 循环的两个整数的幂之和

Java流,如何GROUP BY并查找流的乘积

java - 舍入 BigDecimal 以匹配 C++ sprintf

Java - 将字符串转换为具有 10 位或更多小数的 double 型

hibernate - 具有 BigDecimal 而不是 Long 的实体类 - 生成的 Hibernate 工具

Java BigDecimal.toPlainString() 性能

java - 使用 Struts2 标签格式化数字

java - Android 中应用程序关闭时我们如何打开 Activity