2014-01-29 26 views

回答

7

我相信你想要的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”。上面的代码将小数点前的所有尾随零视为重要的。

+0

你说得对'precision()'不是答案,而是'new BigDecimal(8.6).precision()'不知何故返回'50' ,'new BigDecimal(8.6).stripTrailingZeroes()。precision()'也返回'50'。 – rgettman

+1

@rgettman:这是因为'新的BigDecimal(8.6)'实际上不是8.6 ...它是最接近''double'到'8.6'的确切值。如果你期望得到2,你应该使用'新的BigDecimal(“8.6”)'。只要打印出'新的BigDecimal(8.6)',你就会明白我的意思。 –

+3

另一个问题是'new BigDecimal(“5000.0”)。stripTrailingZeros()。precision()'返回1,但根据接受的定义,你希望它返回5(因为你不会添加'.0'一个数字的结尾,除非它是重要的)。而且,''5000''中的有效数字的数目无论如何都是不明确的。请参阅维基百科中的“重要数字”。 – ajb

1

乔恩的回答下面的修改返回看起来正确的给我的结果:(注意:input.stripTrailingZeros().scale()似乎永远是负面的,这些测试)

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

而且,正如我上面提到的例如,BigDecimal不能区分例如具有一个有效数字的“5000”和具有两个有效数字的“5000”。此外,根据定义,“5000”。 (带有小数点后)应该只有四位有效数字,但BigDecimal无法处理该数字。 (请参阅http://en.wikipedia.org/wiki/Significant_figures以了解我正在使用的定义。)

相关问题