简体   繁体   English

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

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

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?请有人解释为什么会发生这种情况?

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.请注意,在某些步骤中,乘法会产生较小的数字 (980179200 * 18 = 463356416) 或错误的符号 (213837312 * 20 = -18221056),表明存在整数溢出。 But where does the zero come from?但是零从哪里来? Read on.继续阅读。

Keeping in mind that int data type is a 32-bit signed , two's complement integer, 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 correct result正确的结果
  2. is the internal representation of the result (64 bits are used for illustration)是结果的内部表示(64位用于说明)
  3. is the result represented by the two's complement of the lower 32 bits是由低 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:如果乘法只涉及奇数,则结果不会为零。

Computer multiplication is really happening modulo 2^32.计算机乘法实际上是在模 2^32 中发生的。 Once you have accumulated enough powers of two in the multiplicand, then all values will be 0.一旦您在被乘数中积累了足够的 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).乘积高达 42 等于 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 . 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 not converge to 0, despite all the overflowing.编辑:要了解为什么对这个问题的其他回答不完整,请考虑这样一个事实,即仅限于奇数的同一程序不会收敛到 0,尽管所有溢出。

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 int value.输出不再是int值。 Then you will get wrong value because of the overflow.然后你会因为溢出而得到错误的值。

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

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 .int有超过 32 个尾随零时,它会滚动到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 int is made up of the last 8 hex-digits.查看尾随零如何缓慢增长,并注意int由最后 8 个十六进制数字组成。 After multiplying by 42 (0x2A), all 32 bits of an int are zeroes!乘以 42 (0x2A) 后, int所有 32 位都为零!

                                     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)

Somewhere in the middle you get 0 as the product.在中间的某个地方,您会得到0作为产品。 So, your entire product will be 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 i with the number you get 0 as output.每次将i的当前值与数字相乘时,都会得到0作为输出。

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. @kasperd 的评论朝着正确的方向发展。 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.比很多数字将 2 作为主要因素。 In binary this is equal to a left shift.在二进制中,这等于左移。 By commutativity we can multiply with prime factors of 2 first.通过交换性,我们可以先乘以 2 的质因数。 That means we just do a left shift.这意味着我们只需进行左移。

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。

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

Eventually, the calculation overflows, and eventually that overflow leads to a product of zero;最终,计算溢出,最终溢出导致乘积为零; that happens when product == -2147483648 and i == 42 .product == -2147483648i == 42时会发生这种情况。 Try this code out to verify it for yourself (or run the code here ):试试这个代码来自己验证(或在这里运行代码):

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

It is an integer overflow.这是一个整数溢出。

The int data type is 4 bytes, or 32 bits. int 数据类型为 4 字节或 32 位。 Therefore, numbers larger than 2^(32 - 1) - 1 (2,147,483,647) cannot be stored in this data type.因此,大于 2^(32 - 1) - 1 (2,147,483,647) 的数字不能存储在这种数据类型中。 Your numerical values will be incorrect.您的数值将不正确。

For very large numbers, you will want to import and use the class java.math.BigInteger:对于非常大的数字,您需要导入并使用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 long primitive.注意:对于对于 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 ) 包括一些非常好的大数问题,这些问题提供了关于如何练习考虑要使用的适当数据类型。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM