我想要的是一种将双精度转换为字符串的方法,该字符串使用半向上舍入方法进行舍入-即,如果要舍入的小数为5,则始终向上舍入到下一个数字。这是大多数人在大多数情况下所期望的四舍五入的标准方法。

我还希望只显示有效数字,即不应有任何尾随零。

我知道这样做的一种方法是使用String.format方法:

String.format("%.5g%n", 0.912385);

返回:

0.91239

这是很好的,但是它总是显示带有5位小数的数字,即使它们不重要:

String.format("%.5g%n", 0.912300);

返回:

0.91230

另一种方法是使用DecimalFormatter:

DecimalFormat df = new DecimalFormat("#.#####");
df.format(0.912385);

返回:

0.91238

然而,正如您所见,这使用了半偶数舍入。也就是说,如果前一个数字是偶数,它将向下舍入。我想要的是:

0.912385 -> 0.91239
0.912300 -> 0.9123

在Java中实现这一点的最佳方法是什么?


当前回答

这是我发现的只显示两位小数的最简单方法。

double x = 123.123;
System.out.printf( "%.2f", x );

其他回答

我来这里只是想得到一个关于如何舍入数字的简单答案。这是提供这一点的补充答案。

如何在Java中舍入数字

最常见的情况是使用Math.rround()。

Math.round(3.7) // 4

数字四舍五入到最接近的整数。A.5值向上舍入。如果需要不同的舍入行为,可以使用其他数学函数之一。请参阅下面的比较。

圆形的

如上所述,这四舍五入到最接近的整数。5位小数向上舍入。此方法返回int。

Math.round(3.0); // 3
Math.round(3.1); // 3
Math.round(3.5); // 4
Math.round(3.9); // 4

Math.round(-3.0); // -3
Math.round(-3.1); // -3
Math.round(-3.5); // -3 *** careful here ***
Math.round(-3.9); // -4

ceil

任何十进制值都将舍入到下一个整数。它通向天花板。此方法返回一个double。

Math.ceil(3.0); // 3.0
Math.ceil(3.1); // 4.0
Math.ceil(3.5); // 4.0
Math.ceil(3.9); // 4.0

Math.ceil(-3.0); // -3.0
Math.ceil(-3.1); // -3.0
Math.ceil(-3.5); // -3.0
Math.ceil(-3.9); // -3.0

地板

任何十进制值都向下舍入到下一个整数。此方法返回一个double。

Math.floor(3.0); // 3.0
Math.floor(3.1); // 3.0
Math.floor(3.5); // 3.0
Math.floor(3.9); // 3.0

Math.floor(-3.0); // -3.0
Math.floor(-3.1); // -4.0
Math.floor(-3.5); // -4.0
Math.floor(-3.9); // -4.0

rint

这与舍入相似,因为十进制值舍入到最接近的整数。然而,与舍入不同,.5值舍入为偶数。此方法返回一个double。

Math.rint(3.0); // 3.0
Math.rint(3.1); // 3.0
Math.rint(3.5); // 4.0 ***
Math.rint(3.9); // 4.0
Math.rint(4.5); // 4.0 ***
Math.rint(5.5); // 6.0 ***

Math.rint(-3.0); // -3.0
Math.rint(-3.1); // -3.0
Math.rint(-3.5); // -4.0 ***
Math.rint(-3.9); // -4.0
Math.rint(-4.5); // -4.0 ***
Math.rint(-5.5); // -6.0 ***

您也可以使用

DecimalFormat df = new DecimalFormat("#.00000");
df.format(0.912385);

以确保后面有0。

您可以使用BigDecimal

BigDecimal value = new BigDecimal("2.3");
value = value.setScale(0, RoundingMode.UP);
BigDecimal value1 = new BigDecimal("-2.3");
value1 = value1.setScale(0, RoundingMode.UP);
System.out.println(value + "n" + value1);

参考:http://www.javabeat.net/precise-rounding-of-decimals-using-rounding-mode-enumeration/

我同意使用DecimalFormat或BigDecimal的答案。

请先阅读下面的更新!

但是,如果您确实希望舍入双值并获得双值结果,则可以使用上述org.apache.commons.math3.util.Precision.round(..)。该实现使用BigDecimal,速度慢,并且会产生垃圾。

decimal4j库中的DoubleRounder实用程序提供了一种类似但快速且无垃圾的方法:

 double a = DoubleRounder.round(2.0/3.0, 3);
 double b = DoubleRounder.round(2.0/3.0, 3, RoundingMode.DOWN);
 double c = DoubleRounder.round(1000.0d, 17);
 double d = DoubleRounder.round(90080070060.1d, 9);
 System.out.println(a);
 System.out.println(b);
 System.out.println(c);
 System.out.println(d);

将输出

 0.667
 0.666
 1000.0
 9.00800700601E10

看见https://github.com/tools4j/decimal4j/wiki/DoubleRounder-Utility

披露:我参与了decimal4j项目。

更新:正如@iaforek指出的那样,DoubleRounder有时会返回违反直觉的结果。原因是它执行数学上正确的舍入。例如,DoubleRounder.round(256.025d,2)将向下舍入到256.02,因为表示为256.025d的双精度值略小于有理值256.025,因此将向下舍入。

笔记:

这种行为与BigDecimal(double)构造函数非常相似(但与使用字符串构造函数的valueOf(double)不同)。这个问题可以先用双倍的舍入步骤以更高的精度来解决,但它很复杂,我不打算在这里讨论细节

出于这些原因以及本文中提到的所有内容,我不建议使用DoubleRounder。

这是我发现的只显示两位小数的最简单方法。

double x = 123.123;
System.out.printf( "%.2f", x );