为什么通过 Math.pow() return 递减 Integer.MIN_VALUE 相同的值?
Why does decrementing Integer.MIN_VALUE by Math.pow() return the same value?
执行时:
int p=-2147483648;
p-=Math.pow(1,0);
System.out.println(p);
p-=1;
System.out.println(p);
Output: -2147483648
2147483647
那么为什么 Math.pow() 不会溢出数字?
请注意,Math.pow()
使用 Double 类型的参数,returns 使用双精度类型的参数。将其转换为 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
我们通过观察 -2147483648 == Integer.MIN_VALUE
(= -(2³¹)).
开始讨论
表达式 p -= Math.pow(1,0)
具有从 double
到 int
的隐式转换,因为 Math.pow(...)
returns 和 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. Narrowing Primitive Conversion
...
A narrowing conversion of a floating-point number to an integral type T
takes two steps:
In the first step, the floating-point number is converted either to a long
, if T
is long
, or to an int
, if T
is byte
, short
, char
, or int
, as follows:
If the floating-point number is NaN
(§4.2.3), the result of the first step of the conversion is an int
or long 0.
Otherwise, if the floating-point number is not an infinity, the floating-point value is rounded to an integer value V
, rounding toward zero using IEEE 754 round-toward-zero mode (§4.2.3). Then there are two cases:
If T
is long
, and this integer value can be represented as a long
, then the result of the first step is the long
value V
.
Otherwise, if this integer value can be represented as an int
, then the result of the first step is the int
value V
.
Otherwise, one of the following two cases must be true:
The value must be too small (a negative value of large magnitude or negative infinity), and the result of the first step is the smallest representable value of type int
or long
.
The value must be too large (a positive value of large magnitude or positive infinity), and the result of the first step is the largest representable value of type int
or long
.
In the second step:
- If
T
is int
or long
, the result of the conversion is the result of the first step.
...
执行时:
int p=-2147483648;
p-=Math.pow(1,0);
System.out.println(p);
p-=1;
System.out.println(p);
Output: -2147483648
2147483647
那么为什么 Math.pow() 不会溢出数字?
请注意,Math.pow()
使用 Double 类型的参数,returns 使用双精度类型的参数。将其转换为 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
我们通过观察 -2147483648 == Integer.MIN_VALUE
(= -(2³¹)).
表达式 p -= Math.pow(1,0)
具有从 double
到 int
的隐式转换,因为 Math.pow(...)
returns 和 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. Narrowing Primitive Conversion
...
A narrowing conversion of a floating-point number to an integral type
T
takes two steps:
In the first step, the floating-point number is converted either to a
long
, ifT
islong
, or to anint
, ifT
isbyte
,short
,char
, orint
, as follows:
If the floating-point number is
NaN
(§4.2.3), the result of the first step of the conversion is anint
or long 0.Otherwise, if the floating-point number is not an infinity, the floating-point value is rounded to an integer value
V
, rounding toward zero using IEEE 754 round-toward-zero mode (§4.2.3). Then there are two cases:
If
T
islong
, and this integer value can be represented as along
, then the result of the first step is thelong
valueV
.Otherwise, if this integer value can be represented as an
int
, then the result of the first step is theint
valueV
.Otherwise, one of the following two cases must be true:
The value must be too small (a negative value of large magnitude or negative infinity), and the result of the first step is the smallest representable value of type
int
orlong
.The value must be too large (a positive value of large magnitude or positive infinity), and the result of the first step is the largest representable value of type
int
orlong
.In the second step:
- If
T
isint
orlong
, the result of the conversion is the result of the first step....