为何分步与单行调用Math.round保留两位小数结果不同?需强制转换?
为什么分步保留两位小数与单行写法结果存在差异?
我在尝试寻找将小数保留两位小数的简便方法时,编写了如下代码:
double n = 123.4567, o = 123.4567, p = 123.4567; n *= 100; n = Math.round(n); n = n / 100; System.out.println(n); System.out.println(Math.round(o * 100) / 100); System.out.println(((double) Math.round(p * 100)) / 100);
运行后输出为:
123.46 123 123.46
我认为第一种分步实现与第二种单行实现的算法逻辑完全一致,仅写法不同,但二者结果却存在差异。为何单行写法需要添加强制类型转换,而分步写法则无需转换?
原因解析
核心问题出在Java的类型转换规则和整数/浮点数除法的区别上,结合Math.round()的返回值特性来看:
Math.round(double)的返回值是long类型,不是double。- 分步写法的关键:
n *= 100后,n仍是double类型(值为12345.67);- 执行
n = Math.round(n)时,因为n是double类型变量,Java会自动把long类型的返回值(12346)转换为double类型(12346.0)再赋值给n; - 最后
n / 100是double与int的除法,结果为浮点数(12346.0 / 100 = 123.46)。
- 单行写法
Math.round(o * 100) / 100的问题:Math.round(o * 100)返回long类型的12346;- 这里是
long与int的整数除法,Java会直接舍弃小数部分,计算结果为123(12346 ÷ 100 = 123)。
- 第三种写法通过
(double) Math.round(p * 100),把long类型的12346强制转换为double类型的12346.0,后续除法变为浮点数运算,因此得到正确的123.46。
简言之:分步写法中,赋值给double变量的操作自动完成了类型转换;单行写法直接用long做整数除法,自然得不到预期的浮点数结果。
内容的提问来源于stack exchange,提问作者Brandon Luu
相关产品推荐
相关产品推荐

