Почему Java считает, что произведение всех чисел от 10 до 99 равно 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);
    }
}

Пожалуйста, объясните, почему это происходит?

Ответ 1

Вот что делает программа на каждом шаге:

          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

Обратите внимание, что на некоторых шагах умножение приводит к меньшему числу (980179200 * 18 = 463356416) или неправильному знаку (213837312 * 20 = -18221056), что указывает на то, что произошло целочисленное переполнение. Но откуда взялся ноль? Читайте дальше.

Имея в виду, что тип данных 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
  • - правильный результат
  • - внутреннее представление результата (для иллюстрации используются 64 бита)
  • - результат, представленный двумя дополнениями младших 32 бит

Мы знаем, что умножение числа на четное число:

  • сдвигает биты влево и добавляет нулевые биты вправо
  • приводит к четному числу

Таким образом, в основном ваша программа умножает четное число на другой номер, который нулевым образом удаляет исходные биты справа.

PS: Если умножения включают нечетные числа, тогда результат не станет равным нулю.

Ответ 2

Компьютерное умножение действительно происходит по модулю 2 ^ 32. После того, как вы накопили достаточное количество двух в мультипликаторе, тогда все значения будут равны 0.

Здесь мы имеем все четные числа в ряду вместе с максимальной степенью двух, которая делит число, и кумулятивная мощность двух

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

Произведение до 42 равно x * 2 ^ 32 = 0 (mod 2 ^ 32). Последовательность степеней 2 связана с кодами Grey (среди прочего) и выглядит как https://oeis.org/A001511.

EDIT: чтобы узнать, почему другие ответы на этот вопрос неполны, рассмотрим тот факт, что одна и та же программа, ограниченная только нечетными целыми числами, не будет сходиться к 0, несмотря на все переполнения.

Ответ 3

Он выглядит как целочисленное переполнение.

Взгляните на это

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

Вывод:

25977982938941930515945176761070443325092850981258133993315252362474391176210383043658995147728530422794328291965962468114563072000000000000000000000

Выход больше не является значением int. Тогда вы получите неправильное значение из-за переполнения.

Если он переполняется, он возвращается к минимальному значению и продолжается от там. Если он переполняется, он возвращается к максимальному значению и продолжается оттуда.

Подробнее информация

Edit.

Измените свой код следующим образом

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

Вывод:

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

Ответ 4

Это из-за целочисленного переполнения. Когда вы умножаете много четных чисел вместе, двоичное число получает много конечных нулей. Когда у вас есть более 32 конечных нулей для int, он переходит к 0.

Чтобы помочь вам визуализировать это, вот умножения в шестнадцатеричном формате, рассчитанные на тип номера, который не будет переполняться. Посмотрите, как медленно растут конечные нули, и обратите внимание, что int состоит из последних 8 шестнадцатеричных цифр. После умножения на 42 (0x2A) все 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)

Ответ 5

Где-то посередине вы получаете 0 как продукт. Таким образом, весь ваш продукт будет 0.

В вашем случае:

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 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 в качестве вывода.

Ответ 6

Поскольку многие из существующих точек ответа на детали реализации Java и отладочного вывода позволяют взглянуть на математику за двоичным умножением, чтобы действительно ответить на вопрос почему.

Комментарий @kasperd идет в правильном направлении. Предположим, вы не размножаетесь напрямую с номером, а вместо этого с основными факторами этого числа. Чем много цифр будет иметь 2 в качестве основного фактора. В двоичном формате это равно левому сдвигу. Коммутативностью мы можем сначала умножить на простые множители 2. Это означает, что мы просто делаем сдвиг влево.

При взгляде на правила двоичного умножения единственный случай, когда 1 приведет к определенной позиции цифр, - это когда оба значения операнда равны единице.

Таким образом, эффект сдвига влево заключается в том, что младшая битовая позиция 1 при дальнейшем умножении результата увеличивается.

Так как целое число содержит только биты младшего порядка, все они будут установлены в 0, когда простой коэффициент 2 достаточно часто встречается в результате.

Обратите внимание, что для этого анализа не представляет интереса представление двух дополнительных представлений, так как знак результата умножения может быть вычислен независимо от полученного числа. Это означает, что если значение переполняется и становится отрицательным, биты младшего порядка представляются как 1, но во время умножения они снова обрабатываются как 0.

Ответ 7

Если я запустил этот код, то что получаю все -

          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

Целочисленная причина переполнения -

980179200 * 18 =   463356416 (should be 17643225600)

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

Произвести причину 0 -

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

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

Ответ 8

В конце концов, вычисление переполняется, и в конечном итоге это переполнение приводит к нулевому продукту; это происходит, когда 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));
    }
}

Как только он равен нулю, он, конечно, остается равным нулю. Вот какой код, который даст более точный результат (вы можете запустить код здесь):

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

Ответ 9

Это переполнение целых чисел.

Тип данных int - 4 байта или 32 бита. Поэтому числа, превышающие 2 ^ (32 - 1) - 1 (2 147 483 647), не могут быть сохранены в этом типе данных. Ваши числовые значения будут неверными.

Для очень больших чисел вы захотите импортировать и использовать класс 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());

ПРИМЕЧАНИЕ. Для числовых значений, которые все еще слишком велики для типа данных int, но достаточно малы, чтобы соответствовать в пределах 8 байтов (абсолютное значение меньше или равно 2 ^ (64 - 1) - 1), вы, вероятно, должны использовать примитив long.

Практические проблемы HackerRank (www.hackerrank.com), такие как секция практики алгоритмов, (https://www.hackerrank.com/domains/algorithms/warmup) включают некоторые очень хорошие большие - количество вопросов, которые дают хорошую практику о том, как думать о соответствующем типе данных для использования.