为何Math.round(Long.MAX_VALUE+1)返回Integer.MIN_VALUE?类型转换疑问
你遇到的问题核心不在Math.round的参数转换,而是**Long.MAX_VALUE + 1这个表达式的计算顺序和类型溢出**:
表达式计算优先于参数转换
Long.MAX_VALUE是long类型(64位整数),字面量1默认是int类型(32位整数)。按照Java的类型提升规则,int会被自动转为long,所以Long.MAX_VALUE + 1是long类型内部的加法运算。
Long.MAX_VALUE的值是9223372036854775807,加1后会触发long类型的溢出,结果变成-9223372036854775808(也就是Long.MIN_VALUE)。溢出后的long值转double
当这个溢出后的long值被传入Math.round(double)时,会被转为double类型。虽然double的范围比long大,但Long.MIN_VALUE是-2^63,属于double能精确表示的整数范围(double可以精确表示所有±2^53以内的整数,以及2的整数次幂的大数),所以转换后还是-9223372036854775808。最终结果的类型转换(你可能忽略的一步)
Math.round(double)的返回值是long类型。如果你把这个结果直接赋值给int类型变量(或者隐式转换),long类型的Long.MIN_VALUE会被截断为int的低32位,也就是-2147483648,即Integer.MIN_VALUE——这就是你看到的结果。
如果想避免这个问题,需要让加法运算在double类型下进行,比如把其中一个操作数转为double:
Math.round((double)Long.MAX_VALUE + 1);
这样Long.MAX_VALUE先转成double,加1后不会溢出,Math.round会返回9223372036854775808L(因为double能精确表示这个数)。
内容的提问来源于stack exchange,提问作者Gargouri Nourallah

