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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/26375932/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 02:23:49  来源:igfitidea点击:

Why does Java think that the product of all numbers from 10 to 99 is 0?

javaintegerinteger-overflow

提问by Aniruddha Sarkar

The following block of codes gives the output as 0.

以下代码块的输出为 0。

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

Please can somebody explain why this happens?

请有人解释为什么会发生这种情况?

采纳答案by Salman A

Here is what the program does at each step:

以下是程序在每个步骤中的作用:

          1 * 10 =          10
         10 * 11 =         110
        110 * 12 =        1320
       1320 * 13 =       17160
      17160 * 14 =      240240
     240240 * 15 =     3603600
    3603600 * 16 =    57657600
   57657600 * 17 =   980179200
  980179200 * 18 =   463356416
  463356416 * 19 =   213837312
  213837312 * 20 =   -18221056
  -18221056 * 21 =  -382642176
 -382642176 * 22 =   171806720
  171806720 * 23 =  -343412736
 -343412736 * 24 =   348028928
  348028928 * 25 =   110788608
  110788608 * 26 = -1414463488
-1414463488 * 27 =   464191488
  464191488 * 28 =   112459776
  112459776 * 29 = -1033633792
-1033633792 * 30 =  -944242688
 -944242688 * 31 =   793247744
  793247744 * 32 =  -385875968
 -385875968 * 33 =   150994944
  150994944 * 34 =   838860800
  838860800 * 35 =  -704643072
 -704643072 * 36 =   402653184
  402653184 * 37 =  2013265920
 2013265920 * 38 =  -805306368
 -805306368 * 39 = -1342177280
-1342177280 * 40 = -2147483648
-2147483648 * 41 = -2147483648
-2147483648 * 42 =           0
          0 * 43 =           0
          0 * 44 =           0
vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
          0 * 97 =           0
          0 * 98 =           0

Notice that on some steps the multiplication results in a smaller number (980179200 * 18 = 463356416) or incorrect sign (213837312 * 20 = -18221056), indicating that there was an integer overflow. But where does the zero come from? Read on.

请注意,在某些步骤中,乘法会产生较小的数字 (980179200 * 18 = 463356416) 或错误的符号 (213837312 * 20 = -18221056),表明存在整数溢出。但是零从哪里来?继续阅读。

Keeping in mind that intdata type is a 32-bit signed, two's complementinteger, here is an explanation of each step:

牢记int数据类型是签署了32位整,这里是每一个步骤的说明:

Operation         Result(1)     Binary Representation(2)                                           Result(3)
----------------  ------------  -----------------------------------------------------------------  ------------
          1 * 10            10                                                               1010            10
         10 * 11           110                                                            1101110           110
        110 * 12          1320                                                        10100101000          1320
       1320 * 13         17160                                                    100001100001000         17160
      17160 * 14        240240                                                 111010101001110000        240240
     240240 * 15       3603600                                             1101101111110010010000       3603600
    3603600 * 16      57657600                                         11011011111100100100000000      57657600
   57657600 * 17     980179200                                     111010011011000101100100000000     980179200
  980179200 * 18   17643225600                               100 00011011100111100100001000000000     463356416
  463356416 * 19    8803771904                                10 00001100101111101110011000000000     213837312
  213837312 * 20    4276746240                                   11111110111010011111100000000000     -18221056
  -18221056 * 21    -382642176  11111111111111111111111111111111 11101001001100010101100000000000    -382642176
 -382642176 * 22   -8418127872  11111111111111111111111111111110 00001010001111011001000000000000     171806720
  171806720 * 23    3951554560                                   11101011100001111111000000000000    -343412736
 -343412736 * 24   -8241905664  11111111111111111111111111111110 00010100101111101000000000000000     348028928
  348028928 * 25    8700723200                                10 00000110100110101000000000000000     110788608
  110788608 * 26    2880503808                                   10101011101100010000000000000000   -1414463488
-1414463488 * 27  -38190514176  11111111111111111111111111110111 00011011101010110000000000000000     464191488
  464191488 * 28   12997361664                                11 00000110101101000000000000000000     112459776
  112459776 * 29    3261333504                                   11000010011001000000000000000000   -1033633792
-1033633792 * 30  -31009013760  11111111111111111111111111111000 11000111101110000000000000000000    -944242688
 -944242688 * 31  -29271523328  11111111111111111111111111111001 00101111010010000000000000000000     793247744
  793247744 * 32   25383927808                               101 11101001000000000000000000000000    -385875968
 -385875968 * 33  -12733906944  11111111111111111111111111111101 00001001000000000000000000000000     150994944
  150994944 * 34    5133828096                                 1 00110010000000000000000000000000     838860800
  838860800 * 35   29360128000                               110 11010110000000000000000000000000    -704643072
 -704643072 * 36  -25367150592  11111111111111111111111111111010 00011000000000000000000000000000     402653184
  402653184 * 37   14898167808                                11 01111000000000000000000000000000    2013265920
 2013265920 * 38   76504104960                             10001 11010000000000000000000000000000    -805306368
 -805306368 * 39  -31406948352  11111111111111111111111111111000 10110000000000000000000000000000   -1342177280
-1342177280 * 40  -53687091200  11111111111111111111111111110011 10000000000000000000000000000000   -2147483648
-2147483648 * 41  -88046829568  11111111111111111111111111101011 10000000000000000000000000000000   -2147483648
-2147483648 * 42  -90194313216  11111111111111111111111111101011 00000000000000000000000000000000             0
          0 * 43             0                                                                  0             0
vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
          0 * 98             0                                                                  0             0
  1. is the correctresult
  2. is the internal representation of the result (64 bits are used for illustration)
  3. is the result represented by the two's complement of the lower 32 bits
  1. 正确的结果
  2. 是结果的内部表示(64位用于说明)
  3. 是由低 32 位的二进制补码表示的结果

We know that multiplying a number by an even number:

我们知道一个数乘以一个偶数:

  • shifts the bits towards left and adds zero bits towards right
  • results in an even number
  • 将位向左移动并向右添加零位
  • 结果是偶数

So basically your program multiplies an even number with another number repeatedly which zeroes out the result bits starting from right.

所以基本上你的程序将一个偶数与另一个数字重复相乘,从右开始将结果位清零。

PS: If the multiplications involved odd numbers only then the result will not become zero.

PS:如果乘法只涉及奇数,则结果不会为零。

回答by Ruchira Gayan Ranaweera

It looks like an integer overflow.

它看起来像一个整数溢出

Take a look at this

看看这个

BigDecimal product=new BigDecimal(1);
for(int i=10;i<99;i++){
    product=product.multiply(new BigDecimal(i));
}
System.out.println(product);

Output:

输出:

25977982938941930515945176761070443325092850981258133993315252362474391176210383043658995147728530422794328291965962468114563072000000000000000000000

Output no longer be a intvalue. Then you will get wrong value because of the overflow.

输出不再是一个int值。然后你会因为溢出而得到错误的值。

If it overflows, it goes back to the minimum value and continues from there. If it underflows, it goes back to the maximum value and continues from there.

如果它溢出,它会回到最小值并从那里继续。如果它下溢,它会回到最大值并从那里继续。

More info

更多信息

Edit.

编辑

Let's change your code as follows

让我们按如下方式更改您的代码

int product = 1;
for (int i = 10; i < 99; i++) {
   product *= i;
   System.out.println(product);
}

Out put:

输出:

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
-2147483648
-2147483648>>>binary representation is 11111111111111111111111111101011 10000000000000000000000000000000 
 0 >>> here binary representation will become 11111111111111111111111111101011 00000000000000000000000000000000 
 ----
 0

回答by TheLostMind

Somewhere in the middle you get 0as the product. So, your entire product will be 0.

在中间的某个地方,您将获得0产品。因此,您的整个产品将为 0。

In your case :

在你的情况下:

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

Every time you multiply the current value of iwith the number you get 0as output.

每次将 的当前值乘以作为输出i的数字0

回答by Subhrajyoti Majumder

If I run this code What I get all -

如果我运行此代码,我会得到什么 -

          1 * 10 =          10
         10 * 11 =         110
        110 * 12 =        1320
       1320 * 13 =       17160
      17160 * 14 =      240240
     240240 * 15 =     3603600
    3603600 * 16 =    57657600
   57657600 * 17 =   980179200
  980179200 * 18 =   463356416 <- Integer Overflow (17643225600)
  463356416 * 19 =   213837312
  213837312 * 20 =   -18221056
  -18221056 * 21 =  -382642176
 -382642176 * 22 =   171806720
  171806720 * 23 =  -343412736
 -343412736 * 24 =   348028928
  348028928 * 25 =   110788608
  110788608 * 26 = -1414463488
-1414463488 * 27 =   464191488
  464191488 * 28 =   112459776
  112459776 * 29 = -1033633792
-1033633792 * 30 =  -944242688
 -944242688 * 31 =   793247744
  793247744 * 32 =  -385875968
 -385875968 * 33 =   150994944
  150994944 * 34 =   838860800
  838860800 * 35 =  -704643072
 -704643072 * 36 =   402653184
  402653184 * 37 =  2013265920
 2013265920 * 38 =  -805306368
 -805306368 * 39 = -1342177280
-1342177280 * 40 = -2147483648
-2147483648 * 41 = -2147483648
-2147483648 * 42 =           0 <- produce 0 
          0 * 43 =           0


Integer Overflow cause -

整数溢出原因 -

980179200 * 18 =   463356416 (should be 17643225600)

17643225600 : 10000011011100111100100001000000000 <-Actual
MAX_Integer :     1111111111111111111111111111111
463356416   :     0011011100111100100001000000000 <- 32 bit Integer

Produce 0 cause -

产生 0 原因 -

-2147483648 * 42 =           0 (should be -90194313216)

-90194313216: 1010100000000000000000000000000000000 <- Actual
MAX_Integer :       1111111111111111111111111111111
0           :      00000000000000000000000000000000 <- 32 bit Integer

回答by SpaceTrucker

Since many of the existing answer point to implementation details of Java and debug output, lets have a look at the math behind binary multiplication to really answer the why.

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

The comment of @kasperd goes in the right direction. Suppose you do not multiply directly with the number but with the prime factors of that number instead. Than a lot of numbers will have 2 as a prime factor. In binary this is equal to a left shift. By commutativity we can multiply with prime factors of 2 first. That means we just do a left shift.

@kasperd 的评论朝着正确的方向发展。假设您不直接与数字相乘,而是与该数字的质因数相乘。比很多数字将 2 作为主要因素。在二进制中,这等于左移。通过交换性,我们可以先乘以 2 的质因数。这意味着我们只需进行左移。

When having a look at binary multiplication rules, the only case where a 1 will result in a specific digit position is when both operand values are one.

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

So the effect of a left shift is that the lowest bit position of a 1 when further multiplying the result is increased.

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

Since integer contains only the lowest order bits, they all will be set to 0 when the prime factor 2 is cotnained often enough in the result.

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

Note that two's complement representation is not of interest for this analysis, since the sign of the multiplication result can be computed independently from the resulting number. That means if the value overflows and becomes negative, the lowest order bits are represented as 1, but during multiplication they are treated again as being 0.

请注意,此分析不关心二进制补码表示,因为乘法结果的符号可以独立于结果数字计算。这意味着如果值溢出并变为负数,则最低位表示为 1,但在乘法期间它们再次被视为 0。

回答by Trevor

Eventually, the calculation overflows, and eventually that overflow leads to a product of zero; that happens when product == -2147483648and i == 42. Try this code out to verify it for yourself (or run the code here):

最终,计算溢出,最终溢出导致乘积为零;当product == -2147483648和时会发生这种情况i == 42。试试这个代码来自己验证(或在这里运行代码):

import java.math.BigInteger;

class Ideone {
    public static void main (String[] args) throws java.lang.Exception {
        System.out.println("Result: " + (-2147483648 * 42));
    }
}

Once it's zero, it of course stays zero. Here's some code that will produce a more accurate result (you can run the code here):

一旦它为零,它当然保持为零。下面是一些可以产生更准确结果的代码(您可以在此处运行代码):

import java.math.BigInteger;

class Ideone {
    public static void main (String[] args) throws java.lang.Exception {
        BigInteger p = BigInteger.valueOf(1);
        BigInteger start = BigInteger.valueOf(10);
        BigInteger end = BigInteger.valueOf(99);
        for(BigInteger i = start; i.compareTo(end) < 0; i = i.add(BigInteger.ONE)){
            p = p.multiply(i);
            System.out.println("p: " + p);
        }
        System.out.println("\nProduct: " + p);
    }
}

回答by Tim S.

It's because of integer overflow. When you multiply many even numbers together, the binary number gets a lot of trailing zeroes. When you have over 32 trailing zeroes for an int, it rolls over to 0.

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

To help you visualize this, here are the multiplications in hex calculated on a number type that won't overflow. See how the trailing zeroes slowly grow, and note that an intis made up of the last 8 hex-digits. After multiplying by 42 (0x2A), all 32 bits of an intare zeroes!

为了帮助您形象化,以下是对不会溢出的数字类型计算的十六进制乘法。查看尾随零如何缓慢增长,并注意 anint由最后 8 个十六进制数字组成。乘以 42 (0x2A) 后,an 的所有 32 位int都为零!

                                     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)

回答by user295691

Computer multiplication is really happening modulo 2^32. Once you have accumulated enough powers of two in the multiplicand, then all values will be 0.

计算机乘法实际上是在模 2^32 中发生的。一旦您在被乘数中积累了足够的 2 次幂,那么所有值都将为 0。

Here we have all the even numbers in the series, along with the maximum power of two that divides the number, and the cumulative power of two

在这里,我们有系列中的所有偶数,以及除以该数的 2 的最大幂,以及 2 的累积幂

num   max2  total
10    2     1
12    4     3
14    2     4
16    16    8
18    2     9
20    4    11
22    2    12
24    8    15
26    2    16
28    4    18
30    2    19
32    32   24
34    2    25
36    4    27
38    2    28
40    8    31
42    2    32

The product up to 42 is equal to x * 2^32 = 0 (mod 2^32). The sequence of the powers of two is related to Gray codes (among other things), and appears as https://oeis.org/A001511.

乘积高达 42 等于 x * 2^32 = 0 (mod 2^32)。2 的幂的顺序与格雷码(除其他外)有关,并显示为https://oeis.org/A001511

EDIT: to see why other responses to this question are incomplete, consider the fact that the same program, restricted to odd integers only, would notconverge to 0, despite all the overflowing.

编辑:要了解为什么对这个问题的其他回答不完整,请考虑这样一个事实,即仅限于奇数的同一程序不会收敛到 0,尽管所有溢出。

回答by La-comadreja

It is an integer overflow.

这是一个整数溢出。

The int data type is 4 bytes, or 32 bits. Therefore, numbers larger than 2^(32 - 1) - 1 (2,147,483,647) cannot be stored in this data type. Your numerical values will be incorrect.

int 数据类型为 4 字节或 32 位。因此,不能以这种数据类型存储大于 2^(32 - 1) - 1 (2,147,483,647) 的数字。您的数值将不正确。

For very large numbers, you will want to import and use the class java.math.BigInteger:

对于非常大的数字,您将需要导入和使用该类 java.math.BigInteger:

BigInteger product = BigInteger.ONE;
for (long i = 10; i < 99; i++) 
    product = product.multiply(BigInteger.valueOf(i));
System.out.println(product.toString());

NOTE: For numerical values that are still too large for the int data type, but small enough to fit within 8 bytes (absolute value less than or equal to 2^(64 - 1) - 1), you should probably use the longprimitive.

注意:对于对于 int 数据类型来说仍然太大的数值,但小到足以容纳 8 个字节(绝对值小于或等于 2^(64 - 1) - 1),您可能应该使用long原语。

HackerRank's practice problems (www.hackerrank.com), such as the Algorithms practice section, (https://www.hackerrank.com/domains/algorithms/warmup) include some very good large-number questions that give good practice about how to think about the appropriate data type to use.

HackerRank 的练习题 (www.hackerrank.com),例如算法练习部分,( https://www.hackerrank.com/domains/algorithms/warmup) 包括一些非常好的大数问题,这些问题提供了关于如何练习考虑要使用的适当数据类型。