找到BigDecimal中有效位数的简洁方法?

时间:2014-01-29 22:09:44

标签: java bigdecimal significant-digits

我不想限制BigDecimal中的有效位数。我只想查找该号码的有效位数。

有没有办法在不将数字转换为字符串并计算数字字符的情况下执行此操作?

3 个答案:

答案 0 :(得分:9)

我相信你想要stripTrailingZerosprecisionscale的组合,如下所示:

import java.math.*;

public class Test {

    public static void main(String[] args) {
        test("5000");      // 4
        test("5000.00");   // 4
        test("5000.12");   // 6
        test("35000");     // 5
        test("35000.00");  // 5
        test("35000.12");  // 7
        test("35000.120"); // 7
        test("0.0034");    // 2
        test("1.0034");    // 5
        test("1.00340");   // 5
    }


    private static void test(String input) {
        System.out.println(input + " => " +
            significantDigits(new BigDecimal(input)));
    }

    private static int significantDigits(BigDecimal input) {
        input = input.stripTrailingZeros();
        return input.scale() < 0
            ? input.precision() - input.scale()
            : input.precision(); 
    }
}

需要调用stripTrailingZeros,否则BigDecimal完全有可能以“非规范化”形式存储。例如,new BigDecimal(5000)的精度为4,而不是1。

scale()的调用用于处理规范化形式在小数点之前具有尾随零的情况,但小数点之后没有。在这种情况下,比例将始终为负数,并指示尾随零的数量。

编辑:尾随零但没有小数点的情况本质上是模棱两可的 - 例如,没有确定数量的有效数字为“5000”。上面的代码将小数点前的所有尾随零视为重要。

答案 1 :(得分:1)

Jon的答案的以下修改会返回对我来说似乎正确的结果:

private static int significantDigits(BigDecimal input) {
    return input.scale() <= 0
        ? input.precision() + input.stripTrailingZeros().scale()
        : input.precision();
}

(请注意,input.stripTrailingZeros().scale()在这些测试中似乎总是否定。)

此外,如上所述,BigDecimal无法区分,例如,“5000”与一个有效数字和“5000”与两个有效数字,例如。此外,根据定义,“5000”。 (带有一个尾随小数点)应该只有四位有效数字,但BigDecimal无法处理。 (有关我正在使用的定义,请参阅http://en.wikipedia.org/wiki/Significant_figures。)

答案 2 :(得分:0)

在大多数情况下,乔恩的答案是正确的,除了指数数:

private static int significantDigits(BigDecimal input) {
return input.scale() <= 0
    ? input.precision() + input.stripTrailingZeros().scale()
    : input.precision();
}

假设输入为1.230000E17,该函数返回18,但是正确的有效数字应为7。