是否有处理有效数字的Java数字格式库?

时间:2011-03-29 15:07:13

标签: java number-formatting

内置的DecimalFormat只允许您指定小数点右侧的位数。

由于将数字表示为double的限制,数字格式化需要在其中包含一定程度的舍入。在一般情况下,舍入必须是若干有效数字(默认情况下是双精度),否则你的格式化双精度将最终显示像3.5999999而不是3.6的东西。

我能找到的最接近的解决方案是使用

new BigDecimal(double, new MathContext(14, RoundingMode.HALF_EVEN).stripTrailingZeros().toPlainString()
然而,

只提供单一格式。如果我需要对它进行格式化(组分隔符,小数点分隔符,数字限制,填充等),JDK库中没有任何内容。

是否有一般数字格式库可以正确处理有效数字的舍入?

有人问了一些例子。所以,假设我想格式化为4位有效数字,然后:

0.000003599999 -> 0.0000036
4.12345 -> 4.123
1234.345 -> 1234

我们采取的一般方法是舍入到14位数,因为根据具体情况,双倍只能代表大约15-17位有效数字(或者我读过)。

4 个答案:

答案 0 :(得分:10)

这会增加很多开销(5 MB左右),但是International Components for Unicode项目有一个增强的DecimalFormat,可以很好地处理有效数字。

http://icu-project.org/apiref/icu4j/com/ibm/icu/text/DecimalFormat.html#sigdig

DecimalFormat formatter = new DecimalFormat();
formatter.setMaximumSignificantDigits( 4 );
System.out.println( formatter.format( hoursSinceLastAccident ) );

答案 1 :(得分:2)

这样的解决方案怎么样:

double l = 34563.35129854289;
short offset = (short) Math.ceil(Math.log10(l) + 1);
short significantDigits = 10;

System.out.printf("%,." + (significantDigits - offset) + "f", l);
//String output = String.format("%,." + (significantDigits - offset) + "f", l);

输出:

34 563,3513(即printf中的','表示使用组分隔符)

答案 2 :(得分:2)

值得一提的是,如果它特别是 Android 而非Java被定位,内置的DecimalFormat支持重要数据的格式化通过@符号。

String smallPi = new DecimalFormat("@@@").format("3.14159"); // formats number as '3.14'

答案 3 :(得分:-1)

我找到了这样做的好方法。

如果您只是想将其打印出来。

public String toSignificantFiguresString(BigDecimal bd, int significantFigures){
    return String.format("%."+significantFigures+"G", bd);
}

如果你想转换它:

public BigDecimal toSignificantFigures(BigDecimal bd, int significantFigures){
    String s = String.format("%."+significantFigures+"G", bd);
    BigDecimal result = new BigDecimal(s);
    return result;
}

这是一个实际的例子:

    BigDecimal bd2 = toSignificantFigures(BigDecimal.valueOf(4.12345), 4);
    BigDecimal bd3 = toSignificantFigures(BigDecimal.valueOf(1234.345), 4);
    BigDecimal bd4 = toSignificantFigures(BigDecimal.valueOf(0.000003599999), 4);

    System.out.println("bd2: " + String.format("%f",bd2));
    System.out.println("bd3: " + String.format("%f",bd3));
    System.out.println("bd4: " + String.format("%f",bd4));