关于Java:double四舍五入round

Round a double to 2 decimal places

本问题已经有最佳答案,请猛点这里访问。

如果值为200.3456,则应将其格式化为200.34。如果是200,那么应该是200.00


这里有一个实用程序,它将一个双精度数舍入(而不是截断)到指定的小数位数。

例如:

1
round(200.3456, 2); // returns 200.35

原版;当心这个

1
2
3
4
5
6
7
8
public static double round(double value, int places) {
    if (places < 0) throw new IllegalArgumentException();

    long factor = (long) Math.pow(10, places);
    value = value * factor;
    long tmp = Math.round(value);
    return (double) tmp / factor;
}

这在小数位数很高(如round(1000.0d, 17))或整数部分较大(如round(90080070060.1d, 9))的角情况下会很糟糕。感谢斯隆指出了这一点。

多年来,我一直很高兴地使用上面的方法将"不太大"的小数位数四舍五入到小数点后2或3位(例如,为了日志记录,以秒为单位清除时间:27.987654321987->27.99)。但我想最好避免它,因为更可靠的方法很容易获得,代码也更干净。

所以,用这个来代替

(改编自路易斯·瓦瑟曼和肖恩·欧文的回答。)

1
2
3
4
5
6
7
public static double round(double value, int places) {
    if (places < 0) throw new IllegalArgumentException();

    BigDecimal bd = new BigDecimal(value);
    bd = bd.setScale(places, RoundingMode.HALF_UP);
    return bd.doubleValue();
}

注意,HALF_UP是"学校常用的"舍入模式。仔细阅读RoundingMode文档,如果您怀疑您需要其他东西,如银行的Rounding。

当然,如果您愿意的话,您可以将上面的内容内联到一个行程序中:new BigDecimal(value).setScale(places, RoundingMode.HALF_UP).doubleValue()

在任何情况下

始终记住使用floatdouble的浮点表示是不精确的。例如,考虑以下表达式:

1
2
999199.1231231235 == 999199.1231231236 // true
1.03 - 0.41 // 0.6200000000000001

为了精确起见,您需要使用bigdecimal。在这个过程中,使用接受字符串的构造函数,而不是接受双精度字符串的构造函数。例如,尝试执行以下操作:

1
2
System.out.println(new BigDecimal(1.03).subtract(new BigDecimal(0.41)));
System.out.println(new BigDecimal("1.03").subtract(new BigDecimal("0.41")));

关于这个主题的一些优秀的进一步阅读:

  • 项目48:"避免EDCOX1,9,EDCOX1,1",如果Joshua Bloch需要有效的答案(第二ED)
  • 关于浮点运算,每个程序员都应该知道些什么

如果您希望字符串格式而不是(或除此之外)严格取整数字,请参阅其他答案。

具体来说,请注意,round(200, 0)返回200.0。如果您想要输出"200.00",您应该首先对输出结果进行取整,然后对输出结果进行格式化(这在Jesper的答案中有很好的解释)。


如果只想打印小数点后两位数的double,请使用如下方法:

1
2
double value = 200.3456;
System.out.printf("Value: %.2f", value);

如果您希望得到一个String的结果,而不是打印到控制台,请使用带有相同参数的String.format()

1
String result = String.format("%.2f", value);

或使用DecimalFormat类:

1
2
DecimalFormat df = new DecimalFormat("####0.00");
System.out.println("Value:" + df.format(value));


我认为这更容易:

1
2
3
4
5
double time = 200.3456;
DecimalFormat df = new DecimalFormat("#.##");      
time = Double.valueOf(df.format(time));

System.out.println(time); // 200.35

请注意,这实际上会为您进行舍入,而不仅仅是格式化。


最简单的方法,就是做这样的把戏;

1
2
3
4
double val = ....;
val = val*100;
val = Math.round(val);
val = val /100;

如果val的起始值是200.3456,那么它将变为20034.56,然后四舍五入到20035,然后我们将它除以得到200.34。

如果您希望始终取整,我们可以通过强制转换为int来截断:

1
2
3
4
double val = ....;
val = val*100;
val = (double)((int) val);
val = val /100;

这项技术在大多数情况下都有效,因为对于非常大的双精度(正或负)来说,它可能溢出。但如果您知道您的值将在一个适当的范围内,那么这应该对您有用。


Please使用Apache Commons:数学P></

1
Precision.round(10.4567, 2)


1
2
3
function Double round2(Double val) {
    return new BigDecimal(val.toString()).setScale(2,RoundingMode.HALF_UP).doubleValue();
}

注意the toString()!!!!!!!!!!!!!!!!P></

bigdecimal this is because the binary form of the converts精确双!!!!!!!!!!!!!!!P></

这些不同的方法和他们的suggested是失败的案例。P></

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// Always Good!
new BigDecimal(val.toString()).setScale(2,RoundingMode.HALF_UP).doubleValue()

Double val = 260.775d; //EXPECTED 260.78
260.77 - WRONG - new BigDecimal(val).setScale(2,RoundingMode.HALF_UP).doubleValue()

Double val = 260.775d; //EXPECTED 260.78
260.77 - TRY AGAIN - Math.round(val * 100.d) / 100.0d  

Double val = 256.025d; //EXPECTED 256.03d
256.02 - OOPS - new DecimalFormat("0.00").format(val)
// By default use half even, works if you change mode to half_up

Double val = 256.025d; //EXPECTED 256.03d
256.02 - FAIL - (int)(val * 100 + 0.5) / 100.0;


1
2
3
double value= 200.3456;
DecimalFormat df = new DecimalFormat("0.00");      
System.out.println(df.format(value));

1
2
3
double d = 28786.079999999998;
String str = String.format("%1.2f", d);
d = Double.valueOf(str);

例如,如果您真的想要相同的双精度数,但按您想要的方式进行四舍五入,则可以使用bigdecimal。

1
new BigDecimal(myValue).setScale(2, RoundingMode.HALF_UP).doubleValue();


把双数取整通常不是一个人想要的。相反,使用String.format()以所需的格式表示它。


两个舍入数字。非常简单,您基本上是在更新变量,而不是像decimalformat那样只显示目的。

x = Math.floor(x * 100) / 100;


1
value = (int)(value * 100 + 0.5) / 100.0;

在您的问题中,似乎您也希望避免舍入数字?我想.format()会用半上取整,afaik?所以如果你想四舍五入,200.3456应该是200.35,精度为2。但在你的情况下,如果你只想要前2个,然后放弃其余的?

你可以把它乘以100,然后再转换成一个int(或者取数字的底),然后再除以100。

1
2
3
200.3456 * 100 = 20034.56;  
(int) 20034.56 = 20034;  
20034/100.0 = 200.34;

不过,你可能会遇到一些非常大的接近边界的数字的问题。在这种情况下,转换为字符串并进行子字符串处理也同样容易。