如果值为200.3456,则应该将其格式化为200.34。 如果它是200,那么它应该是200.00。
当前回答
下面是一个实用程序,它将双精度数舍入(而不是截断)到指定的小数点后数位。
例如:
round(200.3456, 2); // returns 200.35
原始版本;注意这个
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)),这种情况会严重失败。感谢Sloin指出这一点。
多年来,我一直在愉快地使用上述方法将“不太大”的双数四舍五入到小数点后2或3位(例如,为了记录日志,以秒为单位清理时间:27.987654321987 -> 27.99)。但我想最好还是避免它,因为有更可靠的方法,代码也更干净。
所以,用这个代替
(改编自路易斯·沃瑟曼的回答和肖恩·欧文的回答。)
public static double round(double value, int places) {
if (places < 0) throw new IllegalArgumentException();
BigDecimal bd = BigDecimal.valueOf(value);
bd = bd.setScale(places, RoundingMode.HALF_UP);
return bd.doubleValue();
}
注意HALF_UP是“学校常用的”舍入模式。仔细阅读RoundingMode文档,如果你怀疑你需要其他的东西,比如Bankers '舍入。
当然,如果你愿意,你可以把上面的代码内联到一行代码中: 新BigDecimal(值)。setScale(地方,RoundingMode.HALF_UP) .doubleValue ()
在每种情况下
永远记住,使用float和double的浮点表示是不精确的。 例如,考虑这些表达式:
999199.1231231235 == 999199.1231231236 // true
1.03 - 0.41 // 0.6200000000000001
为了精确起见,您需要使用BigDecimal。在此过程中,使用接受String的构造函数,而不是接受double的构造函数。例如,尝试执行以下命令:
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条:Joshua Bloch在Effective Java(第二版)中的“如果需要精确的答案,避免使用float和double” 关于浮点运算,每个程序员都应该知道的
如果您想要字符串格式,而不是(或除了)严格舍入数字,请参阅其他答案。
具体来说,请注意轮(200,0)返回200.0。如果您想输出“200.00”,您应该首先四舍五入,然后格式化输出结果(这在Jesper的回答中得到了完美的解释)。
其他回答
例如,如果你真的想要相同的双精度,但以你想要的方式四舍五入,你可以使用BigDecimal
new BigDecimal(myValue).setScale(2, RoundingMode.HALF_UP).doubleValue();
四舍五入通常不是一个人想要的。相反,应该使用String.format()以所需的格式表示它。
最简单的方法,就是做一个这样的魔术;
double val = ....;
val = val*100;
val = Math.round(val);
val = val /100;
如果val从200.3456开始,那么它会变成20034.56,然后四舍五入到20035,然后我们除以它得到200.34。
如果你想总是四舍五入,我们可以通过转换为int型来截断:
double val = ....;
val = val*100;
val = (double)((int) val);
val = val /100;
这种技术适用于大多数情况,因为对于非常大的double(正的或负的),它可能会溢出。但如果你知道你的值将在一个适当的范围内,那么这应该对你有用。
double d = 28786.079999999998;
String str = String.format("%1.2f", d);
d = Double.valueOf(str);
下面是一个实用程序,它将双精度数舍入(而不是截断)到指定的小数点后数位。
例如:
round(200.3456, 2); // returns 200.35
原始版本;注意这个
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)),这种情况会严重失败。感谢Sloin指出这一点。
多年来,我一直在愉快地使用上述方法将“不太大”的双数四舍五入到小数点后2或3位(例如,为了记录日志,以秒为单位清理时间:27.987654321987 -> 27.99)。但我想最好还是避免它,因为有更可靠的方法,代码也更干净。
所以,用这个代替
(改编自路易斯·沃瑟曼的回答和肖恩·欧文的回答。)
public static double round(double value, int places) {
if (places < 0) throw new IllegalArgumentException();
BigDecimal bd = BigDecimal.valueOf(value);
bd = bd.setScale(places, RoundingMode.HALF_UP);
return bd.doubleValue();
}
注意HALF_UP是“学校常用的”舍入模式。仔细阅读RoundingMode文档,如果你怀疑你需要其他的东西,比如Bankers '舍入。
当然,如果你愿意,你可以把上面的代码内联到一行代码中: 新BigDecimal(值)。setScale(地方,RoundingMode.HALF_UP) .doubleValue ()
在每种情况下
永远记住,使用float和double的浮点表示是不精确的。 例如,考虑这些表达式:
999199.1231231235 == 999199.1231231236 // true
1.03 - 0.41 // 0.6200000000000001
为了精确起见,您需要使用BigDecimal。在此过程中,使用接受String的构造函数,而不是接受double的构造函数。例如,尝试执行以下命令:
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条:Joshua Bloch在Effective Java(第二版)中的“如果需要精确的答案,避免使用float和double” 关于浮点运算,每个程序员都应该知道的
如果您想要字符串格式,而不是(或除了)严格舍入数字,请参阅其他答案。
具体来说,请注意轮(200,0)返回200.0。如果您想输出“200.00”,您应该首先四舍五入,然后格式化输出结果(这在Jesper的回答中得到了完美的解释)。
推荐文章
- 如何分割逗号分隔的字符串?
- Java字符串—查看字符串是否只包含数字而不包含字母
- Mockito.any()传递带有泛型的接口
- 在IntelliJ 10.5中运行测试时,出现“NoSuchMethodError: org.hamcrest. matcher . descripbemismatch”
- 使用String.split()和多个分隔符
- Java数组有最大大小吗?
- 在Android中将字符串转换为Uri
- 从JSON生成Java类?
- 为什么java.util.Set没有get(int index)?
- Swing和AWT的区别是什么?
- 为什么Java流是一次性的?
- 四舍五入BigDecimal *总是*有两位小数点后
- 设计模式:工厂vs工厂方法vs抽象工厂
- Java:检查enum是否包含给定的字符串?
- 它的意思是:序列化类没有声明一个静态的最终serialVersionUID字段?