执行时:
int p=-2147483648;
p-=Math.pow(1,0);
System.out.println(p);
p-=1;
System.out.println(p);
Output: -2147483648
2147483647
那么为什么Math.pow()不会导致数值溢出呢?
执行时:
int p=-2147483648;
p-=Math.pow(1,0);
System.out.println(p);
p-=1;
System.out.println(p);
Output: -2147483648
2147483647
那么为什么Math.pow()不会导致数值溢出呢?
我们开始讨论观察到 -2147483648 == Integer.MIN_VALUE
(= -(2³¹))。
表达式 p -= Math.pow(1,0)
有一个从 double
到 int
的隐式转换,因为Math.pow(...)
返回一个 double
。 显式转换的表达式如下
p = (int) (p - Math.pow(1,0))
更加分散,我们得到
double d = p - Math.pow(1,0);
p = (int) d;
正如我们所看到的,d
的值为 -2.147483649E9
(= -2147483649.0
)< Integer.MIN_VALUE
。
强制类型转换的行为受 Java 14 JLS, §5.1.3 规定:
5.1.3. 缩小原始类型转换 将浮点数转换为整数类型T
的缩小转换需要两个步骤:long
(如果 T
是 long
),或者转换为int
(如果 T
是 byte
、short
、char
或 int
)。此过程如下:NaN
(§4.2.3),则转换的第一步结果为 int
或 long
的0。
- 否则,如果浮点数不是无穷大,则使用 IEEE 754 round-toward-zero 模式(§4.2.3)将浮点值四舍五入为整数值 V
,向零舍入。然后有两种情况:
- 如果 T
是 long
,并且此整数值可以表示为 long
,则第一步的结果是 V
的 long
值。
- 否则,如果此整数值可以表示为 int
,则第一步的结果是V
的 int
值。
- 否则,以下两种情况之一必须为真:
- 值太小(大数量级的负值或负无穷大),第一步的结果是类型 int
或 long
可以表示的最小值。
- 值太大(大数量级的正值或正无穷大),第一步的结果是类型 int
或 long
可以表示的最大值。T
是 int
或 long
,则转换的结果是第一步的结果。Math.pow()
的参数类型为Double,返回值为double。将其强制转换为int将会得到预期的输出结果:public class MyClass {
public static void main(String args[]) {
int p=-2147483648;
p-=(int)Math.pow(1,0);
System.out.println(p);
p-=1;
System.out.println(p);
}
}
2147483647
2147483646