[英]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
We know that multiplying a number by 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.如果它下溢,它会回到最大值并从那里继续。
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 == -2147483648
和i == 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.