为什么用 Math.pow() 来减小 Integer.MIN_VALUE 会返回相同的值?

huangapple go评论68阅读模式
英文:

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);
输出:-2147483648
         2147483647 

那么为什么 Math.pow() 不会使数字溢出呢?

英文:

on executing :

        int p=-2147483648;
        p-=Math.pow(1,0);  
        System.out.println(p);
        p-=1;
        System.out.println(p);
Output: -2147483648
         2147483647 

So why doesn't Math.pow() overflow the number?

答案1

得分: 5

我们通过观察发现,-2147483648 == Integer.MIN_VALUE(= -(2的31次方))。

表达式p -= Math.pow(1,0)Math.pow(...)返回一个double,因此存在从doubleint的隐式转换。带有显式转换的表达式如下:

p = (int) (p - Math.pow(1,0));

<kbd>Ideone演示</kbd>

进一步展开,我们得到

double d = p - Math.pow(1,0);
p = (int) d;

<kbd>Ideone演示</kbd>

正如我们所见,d的值为-2.147483649E9(= -2147483649.0),小于Integer.MIN_VALUE

转换的行为受Java 14 JLS,§5.1.3控制:

5.1.3. 缩窄的基本类型转换
...
将浮点数转换为整数类型T的缩窄转换分为两步:

  1. 在第一步中,根据以下规则,将浮点数转换为long(如果Tlong)或int(如果Tbyteshortcharint):

    • 如果浮点数是NaN(§4.2.3),转换的第一步结果为intlong的0。

    • 否则,如果浮点数不是无穷大,将浮点值四舍五入为整数值V,使用IEEE 754的向零舍入模式(§4.2.3)。然后有两种情况:

      • 如果Tlong,并且这个整数值可以表示为long,则第一步的结果是longV

      • 否则,如果这个整数值可以表示为int,则第一步的结果是intV

    • 否则,以下两种情况之一必须为真:

      • 值必须太小(具有较大幅度的负值或负无穷大),第一步的结果是可表示的intlong类型的最小值。

      • 值必须太大(具有较大幅度的正值或正无穷大),第一步的结果是可表示的intlong类型的最大值。

在第二步中:

  1. 如果Tintlong,则转换的结果是第一步的结果。
    ...
英文:

We start the discussion by observing that -2147483648 == Integer.MIN_VALUE (= -(2³¹)).

The expression p -= Math.pow(1,0) has an implicit cast from double to int since Math.pow(...) returns a double. The expression with an explicit cast looks like this

p = (int) (p - Math.pow(1,0))

<kbd>Ideone demo</kbd>

Even more spread out, we get

double d = p - Math.pow(1,0);
p = (int) d;

<kbd>Ideone demo</kbd>

As we can see, d has the value -2.147483649E9 (= -2147483649.0) &lt; Integer.MIN_VALUE.

The behaviour of the cast is governed by 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:
>
> 1. 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:
>
> 1. If T is int or long, the result of the conversion is the result of the first step.
>
> ...

答案2

得分: 1

请注意,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

英文:

Please note that Math.pow() operates with arguments of type Double and returns a double. Casting it to int will result in the expected output:

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);
    }
}

The above produces the following output:

2147483647

2147483646

huangapple
  • 本文由 发表于 2020年8月21日 01:17:36
  • 转载请务必保留本文链接:https://go.coder-hub.com/63510154.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定