是否有处理有效数字的 Java 数字格式库?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5474742/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Is there a Java number formatting library that handles significant digits?
提问by mentics
The built in DecimalFormat only allows you to specify number of digits to the right of the decimal place.
内置的 DecimalFormat 只允许您指定小数点右侧的位数。
Because of the limitations of representing numbers as double, number formatting needs to include some level of rounding inside of it. In the general case, that rounding has to be to a number of significant digits (default case is the precision of a double) or else your formatted double will end up showing stuff like 3.5999999 instead of 3.6.
由于将数字表示为 double 的限制,数字格式需要在其内部包含某种程度的舍入。在一般情况下,舍入必须是多个有效数字(默认情况下是双精度),否则您的格式化双精度最终会显示像 3.5999999 而不是 3.6 这样的东西。
The closest solution I could find is using
我能找到的最接近的解决方案是使用
new BigDecimal(double, new MathContext(14, RoundingMode.HALF_EVEN).stripTrailingZeros().toPlainString()
however, that only provides a single format. If I need to format it generally (group separator, decimal separator, limit to number of digits, padding, etc.), there is nothing in the JDK library.
但是,这仅提供了一种格式。如果我一般需要格式化(组分隔符、小数分隔符、限制位数、填充等),JDK库中没有。
Is there a general number formatting library out there that will handle rounding to significant digits properly?
是否有一个通用数字格式库可以正确处理四舍五入到有效数字?
Someone asked for examples. So, let's say I wanted to format to 4 significant digits, then:
有人要求举例。所以,假设我想格式化为 4 位有效数字,然后:
0.000003599999 -> 0.0000036
4.12345 -> 4.123
1234.345 -> 1234
The general approach we would take would be to round to 14 digits since depending on the circumstances, a double can only represent around 15-17 significant digits anyway (or so I've read).
我们采取的一般方法是四舍五入到 14 位,因为根据情况,double 无论如何只能表示大约 15-17 位有效数字(或者我已经读过)。
采纳答案by Shane
This adds a lot of overhead (5 MB or so), but the International Components for Unicode project has an enhanced DecimalFormat that handles significant digits nicely.
这会增加很多开销(5 MB 左右),但 International Components for Unicode 项目具有增强的 DecimalFormat,可以很好地处理有效数字。
http://icu-project.org/apiref/icu4j/com/ibm/icu/text/DecimalFormat.html#sigdig
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 ) );
回答by Grzegorz Szpetkowski
What about such solution:
这样的解决方案怎么样:
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);
Output:
输出:
34?563,3513 (i.e. ',' in printf indicates to use group separator)
34?563,3513(即printf中的','表示使用组分隔符)
回答by Andrew Marshall
It's worth mentioning that if it's specifically Androidand not Java that's being targeted, the built in DecimalFormat
supports formatting for significant figures via the @
symbol.
值得一提的是,如果它是专门针对Android而不是 Java 的目标,则内置DecimalFormat
支持通过@
符号对有效数字进行格式化。
String smallPi = new DecimalFormat("@@@").format("3.14159"); // formats number as '3.14'
回答by HymanDev
I found this nice way of doing it.
我找到了这样做的好方法。
This is if you just want to print it out.
这是如果您只想打印出来。
public String toSignificantFiguresString(BigDecimal bd, int significantFigures){
return String.format("%."+significantFigures+"G", bd);
}
This is if you want to convert it:
这是如果你想转换它:
public BigDecimal toSignificantFigures(BigDecimal bd, int significantFigures){
String s = String.format("%."+significantFigures+"G", bd);
BigDecimal result = new BigDecimal(s);
return result;
}
Here's an example of it in action:
这是它的一个例子:
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));