64位double可以精确地表示整数+/- 253。
鉴于这一事实,我选择使用双类型作为我所有类型的单一类型,因为我的最大整数是一个无符号的32位数字。
但现在我必须打印这些伪整数,但问题是它们也和实际的双精度数混合在一起。
那么如何在Java中很好地打印这些double呢?
我试过String。format("%f", value),这很接近,除了我得到了很多小值的末尾零。
下面是%f的输出示例
232.00000000
0.18000000000
1237875192.0
4.5800000000
0.00000000
1.23450000
我想要的是:
232
0.18
1237875192
4.58
0
1.2345
当然,我可以写一个函数来修剪这些零,但由于字符串操作,这是大量的性能损失。我能用其他格式的代码做得更好吗?
Tom E.和Jeremy S.的答案是不可接受的,因为他们都任意舍入到小数点后两位。请先理解问题再回答。
请注意字符串。Format (Format, args…)依赖于语言环境(见下面的答案)。
请注意字符串。Format (Format, args…)依赖于语言环境,因为它使用用户的默认语言环境进行格式化,也就是说,可能在其中使用逗号甚至空格,如123 456,789或123,456.789,这可能不是您所期望的。
你可能更喜欢使用String.format((Locale)null, format, args…)
例如,
double f = 123456.789d;
System.out.println(String.format(Locale.FRANCE,"%f",f));
System.out.println(String.format(Locale.GERMANY,"%f",f));
System.out.println(String.format(Locale.US,"%f",f));
打印
123456,789000
123456,789000
123456.789000
这就是String的内容。Format (Format, args…)
EDIT好的,既然已经讨论了有关手续的问题:
res += stripFpZeroes(String.format((Locale) null, (nDigits!=0 ? "%."+nDigits+"f" : "%f"), value));
...
protected static String stripFpZeroes(String fpnumber) {
int n = fpnumber.indexOf('.');
if (n == -1) {
return fpnumber;
}
if (n < 2) {
n = 2;
}
String s = fpnumber;
while (s.length() > n && s.endsWith("0")) {
s = s.substring(0, s.length()-1);
}
return s;
}
我在JSF应用程序中使用它来格式化数字,而不带后面的零。最初的内置格式化程序要求您指定小数位数的最大数量,如果您有太多小数位数,这在这里也很有用。
/**
* Formats the given Number as with as many fractional digits as precision
* available.<br>
* This is a convenient method in case all fractional digits shall be
* rendered and no custom format / pattern needs to be provided.<br>
* <br>
* This serves as a workaround for {@link NumberFormat#getNumberInstance()}
* which by default only renders up to three fractional digits.
*
* @param number
* @param locale
* @param groupingUsed <code>true</code> if grouping shall be used
*
* @return
*/
public static String formatNumberFraction(final Number number, final Locale locale, final boolean groupingUsed)
{
if (number == null)
return null;
final BigDecimal bDNumber = MathUtils.getBigDecimal(number);
final NumberFormat numberFormat = NumberFormat.getNumberInstance(locale);
numberFormat.setMaximumFractionDigits(Math.max(0, bDNumber.scale()));
numberFormat.setGroupingUsed(groupingUsed);
// Convert back for locale percent formatter
return numberFormat.format(bDNumber);
}
/**
* Formats the given Number as percent with as many fractional digits as
* precision available.<br>
* This is a convenient method in case all fractional digits shall be
* rendered and no custom format / pattern needs to be provided.<br>
* <br>
* This serves as a workaround for {@link NumberFormat#getPercentInstance()}
* which does not renders fractional digits.
*
* @param number Number in range of [0-1]
* @param locale
*
* @return
*/
public static String formatPercentFraction(final Number number, final Locale locale)
{
if (number == null)
return null;
final BigDecimal bDNumber = MathUtils.getBigDecimal(number).multiply(new BigDecimal(100));
final NumberFormat percentScaleFormat = NumberFormat.getPercentInstance(locale);
percentScaleFormat.setMaximumFractionDigits(Math.max(0, bDNumber.scale() - 2));
final BigDecimal bDNumberPercent = bDNumber.multiply(new BigDecimal(0.01));
// Convert back for locale percent formatter
final String strPercent = percentScaleFormat.format(bDNumberPercent);
return strPercent;
}
这是另一个答案,它有一个选项,只有当小数不为零时才附加小数。
/**
* Example: (isDecimalRequired = true)
* d = 12345
* returns 12,345.00
*
* d = 12345.12345
* returns 12,345.12
*
* ==================================================
* Example: (isDecimalRequired = false)
* d = 12345
* returns 12,345 (notice that there's no decimal since it's zero)
*
* d = 12345.12345
* returns 12,345.12
*
* @param d float to format
* @param zeroCount number decimal places
* @param isDecimalRequired true if it will put decimal even zero,
* false will remove the last decimal(s) if zero.
*/
fun formatDecimal(d: Float? = 0f, zeroCount: Int, isDecimalRequired: Boolean = true): String {
val zeros = StringBuilder()
for (i in 0 until zeroCount) {
zeros.append("0")
}
var pattern = "#,##0"
if (zeros.isNotEmpty()) {
pattern += ".$zeros"
}
val numberFormat = DecimalFormat(pattern)
var formattedNumber = if (d != null) numberFormat.format(d) else "0"
if (!isDecimalRequired) {
for (i in formattedNumber.length downTo formattedNumber.length - zeroCount) {
val number = formattedNumber[i - 1]
if (number == '0' || number == '.') {
formattedNumber = formattedNumber.substring(0, formattedNumber.length - 1)
} else {
break
}
}
}
return formattedNumber
}
请注意字符串。Format (Format, args…)依赖于语言环境,因为它使用用户的默认语言环境进行格式化,也就是说,可能在其中使用逗号甚至空格,如123 456,789或123,456.789,这可能不是您所期望的。
你可能更喜欢使用String.format((Locale)null, format, args…)
例如,
double f = 123456.789d;
System.out.println(String.format(Locale.FRANCE,"%f",f));
System.out.println(String.format(Locale.GERMANY,"%f",f));
System.out.println(String.format(Locale.US,"%f",f));
打印
123456,789000
123456,789000
123456.789000
这就是String的内容。Format (Format, args…)
EDIT好的,既然已经讨论了有关手续的问题:
res += stripFpZeroes(String.format((Locale) null, (nDigits!=0 ? "%."+nDigits+"f" : "%f"), value));
...
protected static String stripFpZeroes(String fpnumber) {
int n = fpnumber.indexOf('.');
if (n == -1) {
return fpnumber;
}
if (n < 2) {
n = 2;
}
String s = fpnumber;
while (s.length() > n && s.endsWith("0")) {
s = s.substring(0, s.length()-1);
}
return s;
}