乐趣区

关于java:Java中一个普通的循环为何从10开始到99连续相乘会得到0

这是一块非常简单的 Java 代码片段:

public class HelloWorld{public static void main(String []args){

        int product = 1;

        for (int i = 10; i <= 99; i++) {product *= i;}

        System.out.println(product);

    }

}

为什么得出的后果是 0 呢?

问题景象

蛋疼的同学可能会发现这个程序执行的法则:

1 * 10 = 10

10 * 11 = 110

110 * 12 = 1320

1320 * 13 = 17160

17160 * 14 = 240240

240240 * 15 = 3603600

3603600 * 16 = 57657600

57657600 * 17 = 980179200

……

-1342177280 * 40 = -2147483648

-2147483648 * 41 = -2147483648

-2147483648 * 42 = 0

0 * 43 = 0

0 * 44 = 0

……

0 * 97 = 0

0 * 98 = 0
程序从 42 开始就曾经输入 0,所以 42 当前的数字相乘的后果就不言而喻了。从后果中发现,乘积的符号已一种难以了解的形式变换着,表明乘积曾经溢出了,同时也阐明 Java 并不会理睬整数的高低溢出。

问题解答
请记住 Java 的 int 类型是 32 位的有符号二进制补码示意的数字类型(译者注:64 为 jdk 同样如此)。这是每一步乘法在计算机外部所做的操作:


标注 (1) 是理论十进制后果。

标注 (2) 十六进制以及十进制的外部示意后果,int 类型只会存储低 32 位的数据。

标注 (3) 是标注 (2) 的补码模式。

如果你好奇 0 从哪里来,请认真看上方 2 进制示意的后果。仔细的同学会留神到:

任何一个数与偶数相乘得偶数。

偶数与偶数相乘,会将 2 进制位整体左移,0 从左边填补空位。

偶数与奇数相乘,不会扭转最右方 0 的数量。

当乘法执行的足够屡次时,右方的 0 位会越来越多。最终,间断乘到 42 时,乘积的 2 进制示意的低 32 位全是 0,所以 int 将会是 0。

问题扩大

既然晓得了问题的起因,咱们换一种变量来做同样的操作,以 byte 为例。

Java 的 byte 变量是 8 位的有符号数,同样也是补码示意。从上方后果表格看出,间断从 10 乘到 16 时,2 进制后果的低 8 位全都是 0,所以此时的 byte 变量是 0。而间断乘到 15 时,低 8 位是 10010000,还记得怎么由补码求原码吗?很简略,符号位不变,其余位取反加 1,得出 11110000,既 -112,感兴趣的敌人请在本人机器上验证后果。有趣味的同学能够退出技术探讨群:626267345

退出移动版