Round a double to 2 decimal places
如果值为
这里有一个实用程序,它将一个双精度数舍入(而不是截断)到指定的小数位数。
例如:
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; } |
这在小数位数很高(如
多年来,我一直很高兴地使用上面的方法将"不太大"的小数位数四舍五入到小数点后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(); } |
注意,
当然,如果您愿意的话,您可以将上面的内容内联到一个行程序中:
始终记住使用
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)
- 关于浮点运算,每个程序员都应该知道些什么
如果您希望字符串格式而不是(或除此之外)严格取整数字,请参阅其他答案。
具体来说,请注意,
如果只想打印小数点后两位数的
1 2 |
如果您希望得到一个
或使用
1 2 |
我认为这更容易:
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 |
如果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)); |
例如,如果您真的想要相同的双精度数,但按您想要的方式进行四舍五入,则可以使用bigdecimal。
1 |
把双数取整通常不是一个人想要的。相反,使用
两个舍入数字。非常简单,您基本上是在更新变量,而不是像decimalformat那样只显示目的。
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; |
不过,你可能会遇到一些非常大的接近边界的数字的问题。在这种情况下,转换为字符串并进行子字符串处理也同样容易。