将double格式化为去除不必要的“.0”并永远不舍入

9

我知道如何格式化一个双精度数,只保留可用的小数位(DP),最多保留一定数量的 DP。这个例子保留了最多4个 DP。

    double d = 1.0;
    DecimalFormat df = new DecimalFormat("#.####");
    System.out.print(df.format(d)); // returns "1"

    double d = 1.23;
    DecimalFormat df = new DecimalFormat("#.####");
    System.out.print(df.format(d)); // returns "1.23"

    double d = 1.2345678;
    DecimalFormat df = new DecimalFormat("#.####");
    System.out.print(df.format(d)); // returns "1.2346", rounding off: bad!

现在我希望整数值例如1.0返回"1",去除不必要的.0,使用#格式字符提供了这种功能。但是我如何确保数字永远不会四舍五入?是否有其他方法,而不是一个任意长的#链,例如"#.###########################################"
或者我是否应该只使用默认的double转换为字符串,并在末尾截断".0"
    String s = "" + d;
    if(s.substring(s.length()-2).equals(".0")) {
        s=s.substring(0, s.length()-2);
    }

两种方法看起来都非常笨拙。
3个回答

16

我使用以下代码:

double d =
String s = (long) d == d ? "" + (long) d : "" + d; 

如果你需要 Double 而非 double。 (个人建议尽可能避免使用包装器)

Double d =
String s = d.longValue() == d ? "" + d.longValue() : "" + d; 

2
即使编译器可能会对其进行优化,我认为使用String.valueOf(x)而不是"" + x更好。 - rurouni
@rurouni 很多人会同意你的看法。然而,我更喜欢简单的代码,因为它读写起来更快,节省了你的时间。如果性能是个问题,我仍然不会使用valueOf,因为它会创建对象。 - Peter Lawrey
2
@peter: "" + d 也会在内部调用 String.valueOf()。它将被转换为等效于 "new StringBuilder().append("").append(String.valueOf(d)).toString()" 创建更多的对象。 - rurouni
+1 谢谢。我刚意识到我应该使用 Double 而不是 double。所以我想我只需要使用 (long) (double) d 而不是仅仅 (long) d (它无法编译)。 - Jean-François Corbett
谢谢。我使用Double包装器,因为我想将这些数字包含在ArrayList中。 - Jean-François Corbett
显示剩余3条评论

0

默认情况下,DecimalFormat 的舍入模式为向上取整。您可以使用 setRoundingMode() 方法设置不同的舍入格式以满足您的需求。

设置舍入模式的示例代码

double d = 1.2345678;
        DecimalFormat df = new DecimalFormat("#.####");
        df.setRoundingMode(RoundingMode.DOWN);
        System.out.print(df.format(d));//result 1.2345 because of rounding down

如何确保数字不会四舍五入? - Jean-François Corbett
@Jean-FrançoisCorbett:除非您使用二进制或任何2^n进制系统(例如八进制或十六进制),否则您无法这样做。 - rurouni
当然,我知道浮点数算术,但这并不是问题的重点。我如何确保数字的字符串表示形式不会被舍入为除 ""+d 以外的其他内容?这个答案明确地进行了舍入,这恰恰是我所提问的相反情况。 - Jean-François Corbett

-1
你可以使用 Double.doubleToLongBits() 方法并提取指数和尾数。从 API 文档中可以看到:

第 63 位(由掩码 0x8000000000000000L 选择的位)表示浮点数的符号。第 62-52 位(由掩码 0x7ff0000000000000L 选择的位)表示指数。第 51-0 位(由掩码 0x000fffffffffffffL 选择的位)表示浮点数的有效数字(有时称为尾数)。

指数可用于确定有效数字的数量,但您始终需要在某个时候进行四舍五入,因为某些二进制双精度值在十进制中将是无限的。
对于二进制表示,您可以简单地使用尾数,并将小数点放在正确的位置(必要时用零填充)。

大多数非整数十进制值不能表示为二进制数,例如0.1。因此,它将近似为0.10000000000000000000001或类似值。也许您应该考虑所显示的表示法误差有多大(或者前一次计算中还剩下多少有效数字)。 - rurouni
抱歉,我错过了问题,它只涉及整数,但我会留下来,以防有人能用它;-) - rurouni

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接