4

我不想限制 BigDecimal 中的有效位数。我只想找到该数字的有效位数。

有没有办法在不将数字转换为字符串并计算数字字符的情况下做到这一点?

4

3 回答 3

10

我相信您想要 , 和 的组合stripTrailingZerosprecision如下scale所示:

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(); 
    }
}

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

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

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

于 2014-01-29T22:19:41.690 回答
1

Jon's answer的以下修改返回了对我来说似乎正确的结果:

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 。)

于 2014-01-29T23:16:28.163 回答
0

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

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

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

于 2018-11-23T08:22:43.070 回答