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


当前回答

0.0 -> 0% 1.0 -> 100% 0.1 -> 10% 0.11 -> 11% 0.01 -> 1% 0.111 -> 11.1% 0.001 -> 0.1% 0.1111 -> 11.11% 0.0001 -> 0.01%

添加".replace()"是因为我总是使用错误的分隔符

import java.text.NumberFormat

fun Double.formating(): String {
    val defaultFormat: NumberFormat = NumberFormat.getPercentInstance()
    defaultFormat.minimumFractionDigits = 0
    defaultFormat.maximumFractionDigits = 2

    return defaultFormat.format(this).replace(",", ".")
}

其他回答

你说你选择用双类型存储你的数字。我认为这可能是问题的根源,因为它迫使您将整数存储为双精度(因此丢失了关于值性质的初始信息)。将数字存储在Number类(Double和Integer的超类)的实例中,并依赖多态性来确定每个数字的正确格式如何?

我知道重构整个代码可能是不可接受的,但它可以在不需要额外的代码/强制转换/解析的情况下产生所需的输出。

例子:

import java.util.ArrayList;
import java.util.List;

public class UseMixedNumbers {

    public static void main(String[] args) {
        List<Number> listNumbers = new ArrayList<Number>();

        listNumbers.add(232);
        listNumbers.add(0.18);
        listNumbers.add(1237875192);
        listNumbers.add(4.58);
        listNumbers.add(0);
        listNumbers.add(1.2345);

        for (Number number : listNumbers) {
            System.out.println(number);
        }
    }

}

将产生以下输出:

232
0.18
1237875192
4.58
0
1.2345

我的观点是:

if(n % 1 == 0) {
    return String.format(Locale.US, "%.0f", n));
} else {
    return String.format(Locale.US, "%.1f", n));
}

用分组、四舍五入和没有不必要的零(双位数)格式化价格。

规则:

末尾没有零(2.0000 = 2;1.0100000 = 1.01) 一个点后最多两位数(2.010 = 2.01;0.20 = 0.2) 一个点后的第二位数字(1.994 = 1.99;1.995 = 2;1.006 = 1.01;0.0006 -> 0 返回0 (null/-0 = 0) 增加$ (= $56/-$56) 分组(101101.02 = $101,101.02)

更多的例子:

-99.985 = -$99.99 10 = $10 10.00 = $10 20.01000089 = $20.01

它是用Kotlin编写的,作为Double的一个有趣的扩展(因为它在Android中使用),但它可以很容易地转换为Java,因为使用了Java类。

/**
 * 23.0 -> $23
 *
 * 23.1 -> $23.1
 *
 * 23.01 -> $23.01
 *
 * 23.99 -> $23.99
 *
 * 23.999 -> $24
 *
 * -0.0 -> $0
 *
 * -5.00 -> -$5
 *
 * -5.019 -> -$5.02
 */
fun Double?.formatUserAsSum(): String {
    return when {
        this == null || this == 0.0 -> "$0"
        this % 1 == 0.0 -> DecimalFormat("$#,##0;-$#,##0").format(this)
        else -> DecimalFormat("$#,##0.##;-$#,##0.##").format(this)
    }
}

使用方法:

var yourDouble: Double? = -20.00
println(yourDouble.formatUserAsSum()) // will print -$20

yourDouble = null
println(yourDouble.formatUserAsSum()) // will print $0

关于DecimalFormat: https://docs.oracle.com/javase/6/docs/api/java/text/DecimalFormat.html

使用DecimalFormat和setMinimumFractionDigits(0)。

对于Kotlin,你可以使用这样的扩展:

fun Double.toPrettyString() =
    if(this - this.toLong() == 0.0)
        String.format("%d", this.toLong())
    else
        String.format("%s", this)