首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >为什么Java认为从10到99的所有数字的乘积都是0?

为什么Java认为从10到99的所有数字的乘积都是0?
EN

Stack Overflow用户
提问于 2014-10-15 14:34:01
回答 5查看 30.9K关注 0票数 132

下面的代码块给出的输出为0。

代码语言:javascript
复制
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);
    }
}

有人能解释一下为什么会发生这种情况吗?

EN

回答 5

Stack Overflow用户

发布于 2014-10-16 03:49:34

这是因为整数溢出。当你将许多偶数相乘时,二进制数会得到很多尾随的零。当int的尾随零超过32个时,它会转到0

为了帮助您可视化这一点,这里是在不会溢出的number类型上计算的十六进制乘法。看看尾随的零是如何慢慢增长的,并注意int是由最后8个十六进制数字组成的。乘以42 (0x2A)后,int的所有32位均为零!

代码语言:javascript
复制
                                     1 (int: 00000001) * 0A =
                                     A (int: 0000000A) * 0B =
                                    6E (int: 0000006E) * 0C =
                                   528 (int: 00000528) * 0D =
                                  4308 (int: 00004308) * 0E =
                                 3AA70 (int: 0003AA70) * 0F =
                                36FC90 (int: 0036FC90) * 10 =
                               36FC900 (int: 036FC900) * 11 =
                              3A6C5900 (int: 3A6C5900) * 12 =
                             41B9E4200 (int: 1B9E4200) * 13 =
                            4E0CBEE600 (int: 0CBEE600) * 14 =
                           618FEE9F800 (int: FEE9F800) * 15 =
                          800CE9315800 (int: E9315800) * 16 =
                         B011C0A3D9000 (int: 0A3D9000) * 17 =
                        FD1984EB87F000 (int: EB87F000) * 18 =
                      17BA647614BE8000 (int: 14BE8000) * 19 =
                     25133CF88069A8000 (int: 069A8000) * 1A =
                    3C3F4313D0ABB10000 (int: ABB10000) * 1B =
                   65AAC1317021BAB0000 (int: 1BAB0000) * 1C =
                  B1EAD216843B06B40000 (int: 06B40000) * 1D =
                142799CC8CFAAFC2640000 (int: C2640000) * 1E =
               25CA405F8856098C7B80000 (int: C7B80000) * 1F =
              4937DCB91826B2802F480000 (int: 2F480000) * 20 =
             926FB972304D65005E9000000 (int: E9000000) * 21 =
           12E066E7B839FA050C309000000 (int: 09000000) * 22 =
          281CDAAC677B334AB9E732000000 (int: 32000000) * 23 =
         57BF1E59225D803376A9BD6000000 (int: D6000000) * 24 =
        C56E04488D526073CAFDEA18000000 (int: 18000000) * 25 =
      1C88E69E7C6CE7F0BC56B2D578000000 (int: 78000000) * 26 =
     43C523B86782A6DBBF4DE8BAFD0000000 (int: D0000000) * 27 =
    A53087117C4E76B7A24DE747C8B0000000 (int: B0000000) * 28 =
  19CF951ABB6C428CB15C2C23375B80000000 (int: 80000000) * 29 =
 4223EE1480456A88867C311A3DDA780000000 (int: 80000000) * 2A =
AD9E50F5D0B637A6610600E4E25D7B00000000 (int: 00000000)
票数 22
EN

Stack Overflow用户

发布于 2014-10-15 14:38:32

在中间的某个地方,你会得到0作为产品。因此,您的整个乘积将为0。

在您的案例中:

代码语言:javascript
复制
for (int i = 10; i < 99; i++) {
    if (product < Integer.MAX_VALUE)
        System.out.println(product);
    product *= i;
}
// System.out.println(product);

System.out.println(-2147483648 * EvenValueOfi); // --> this is the culprit (Credits : Kocko's answer )

O/P :
1
10
110
1320
17160
240240
3603600
57657600
980179200
463356416
213837312
-18221056
-382642176
171806720
-343412736
348028928
110788608
-1414463488
464191488
112459776
-1033633792
-944242688
793247744
-385875968
150994944
838860800
-704643072
402653184
2013265920
-805306368
-1342177280  --> Multiplying this and the current value of `i` will also give -2147483648 (INT overflow)
-2147483648  --> Multiplying this and the current value of `i` will also give -2147483648 (INT overflow)

-2147483648  ->  Multiplying this and the current value of 'i' will give 0 (INT overflow)
0
0
0

每次将i的当前值与数字相乘时,都会得到0作为输出。

票数 14
EN

Stack Overflow用户

发布于 2014-10-15 20:13:19

由于许多现有的答案都指向Java和调试输出的实现细节,让我们来看看二进制乘法背后的数学原理,以真正回答其中的原因。

@kasperd的评论是正确的。假设你不是直接与数字相乘,而是与该数字的素数因子相乘。很多数字都会有2作为质数因子。在二进制中,这等于左移。通过交换性,我们可以先与2的素数因子相乘。这意味着我们只需要做一个左移。

查看二进制乘法规则时,1将导致特定数字位置的唯一情况是当两个操作数值都为1时。

因此,左移位的效果是,当进一步乘以结果时,1的最低位位置增加。

由于integer只包含最低阶位,因此当素数因数2在结果中经常出现时,它们都将被设置为0。

请注意,2的补码表示对于此分析并不重要,因为乘法结果的符号可以独立于结果数计算。这意味着如果值溢出并变为负数,则最低阶位将表示为1,但在乘法过程中,它们将再次被视为0。

票数 12
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26375932

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档