是否有处理有效数字的Java数字格式化库?
内置的DecimalFormat仅允许您指定小数点右侧的位数 由于将数字表示为双精度的限制,数字格式需要在其中包含一定程度的舍入。在一般情况下,舍入必须是有效数字(默认情况下是双精度),否则格式化的双精度将显示3.599999而不是3.6 我能找到的最接近的解决方案是使用是否有处理有效数字的Java数字格式化库?,java,number-formatting,Java,Number Formatting,内置的DecimalFormat仅允许您指定小数点右侧的位数 由于将数字表示为双精度的限制,数字格式需要在其中包含一定程度的舍入。在一般情况下,舍入必须是有效数字(默认情况下是双精度),否则格式化的双精度将显示3.599999而不是3.6 我能找到的最接近的解决方案是使用 new BigDecimal(double, new MathContext(14, RoundingMode.HALF_EVEN).stripTrailingZeros().toPlainString() 但是,这只提供了
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位左右的有效数字(或者我已经读过了)。这种解决方案怎么样:
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 5633513(即printf中的“,”表示使用组分隔符)这增加了大量开销(5 MB左右),但国际Unicode组件项目有一个增强的十进制格式,可以很好地处理有效数字
我发现这样做很好 这是如果你只想打印出来的话
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));
值得一提的是,如果针对的是Android而不是Java,则内置的
十进制格式支持通过@
符号格式化有效数字
String smallPi = new DecimalFormat("@@@").format("3.14159"); // formats number as '3.14'
问题是“是否有一个通用的数字格式库…”。您的解决方案既有用又有趣,但仅限于printf提供的解决方案。我们可以采取类似的方法,动态创建十进制格式,但无论哪种方法都有点像黑客,我会担心角落大小写和正确的舍入。@taotree,您可以对String.format()
使用相同的黑客。您甚至可以在此基础上构建自己的NumberFormat
。这可能不是最有效的方法,但是…为了更清楚,我建议您发布一些示例,说明对于给定的输入,您期望输出是什么。请注意,新的bigdecime(double)
构造函数以及采用MathContext的版本存在精度问题。改为使用bigdecim.valueOf(…)
。为此,我必须添加setsignificandigitsused(true)
以确保使用有效数字。类android.icu.text.DecimalFormat
支持“@”符号来表示有效数字,但常规java.text.DecimalFormat
不支持。
String smallPi = new DecimalFormat("@@@").format("3.14159"); // formats number as '3.14'