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…)依赖于语言环境(见下面的答案)。


当前回答

我在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;
}

其他回答

不,没关系。由于字符串操作造成的性能损失为零。

下面是修饰%f后面结尾的代码:

private static String trimTrailingZeros(String number) {
    if(!number.contains(".")) {
        return number;
    }

    return number.replaceAll("\\.?0*$", "");
}
float price = 4.30;
DecimalFormat format = new DecimalFormat("0.##"); // Choose the number of decimal places to work with in case they are different than zero and zero value will be removed
format.setRoundingMode(RoundingMode.DOWN); // Choose your Rounding Mode
System.out.println(format.format(price));

以下是一些测试的结果:

4.30     => 4.3
4.39     => 4.39  // Choose format.setRoundingMode(RoundingMode.UP) to get 4.4
4.000000 => 4
4        => 4
String s = "1.210000";
while (s.endsWith("0")){
    s = (s.substring(0, s.length() - 1));
}

这将使字符串丢弃0-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;
}

考虑locale的简单解决方案:

double d = 123.45;
NumberFormat numberFormat = NumberFormat.getInstance(Locale.GERMANY);
System.out.println(numberFormat.format(d));

由于在德国使用逗号作为小数分隔符,因此上面将打印:

123,