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

2022-09-03 01:44:16

内置的DecimalFormat仅允许您指定小数点右边的位数。

由于将数字表示为双精度值的限制,数字格式设置需要在其内部包含某种级别的舍入。在一般情况下,舍入必须为有效位数(默认情况是双精度),否则格式化的双精度最终将显示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位数字,因为根据情况,double无论如何都只能表示大约15-17位有效数字(或者我已经读过)。


答案 1

这增加了很多开销(5 MB左右),但是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 ) );

答案 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 中的 ',' 表示使用组分隔符)