web-dev-qa-db-fra.com

Pourquoi Java pense-t-il que le produit de tous les nombres de 10 à 99 est 0?

Le bloc de codes suivant donne la sortie à 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);
    }
}

S'il vous plaît quelqu'un peut expliquer pourquoi cela se produit?

131
Aniruddha Sarkar

Voici ce que le programme fait à chaque étape:

          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

Notez que sur certaines étapes, la multiplication donne un nombre plus petit (980179200 * 18 = 463356416) ou un signe incorrect (213837312 * 20 = -18221056), ce qui indique un dépassement d'entier. Mais d'où vient le zéro? Continuer à lire.

Gardant à l'esprit que int type de données est une signature 32 bits , complément à deux entier, voici une explication de chaque étape:

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. le résultat correct
  2. est la représentation interne du résultat (64 bits sont utilisés pour l'illustration)
  3. est le résultat représenté par le complément à deux des 32 bits inférieurs

Nous savons que multiplier un nombre par un nombre pair:

  • décale les bits vers la gauche et ajoute zéro bits vers la droite
  • résulte en un nombre pair

Donc, fondamentalement, votre programme multiplie un nombre pair par un autre nombre à plusieurs reprises, ce qui met à zéro les bits de résultat en partant de la droite.

PS: Si les multiplications ne comprennent que des nombres impairs, le résultat ne sera pas nul.

425
Salman A

La multiplication informatique se passe vraiment modulo 2 ^ 32. Une fois que vous avez accumulé suffisamment de puissances de deux dans le multiplicande, toutes les valeurs seront 0.

Nous avons ici tous les nombres pairs de la série, ainsi que la puissance maximale de deux qui divise le nombre et la puissance cumulée de deux.

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

Le produit jusqu'à 42 est égal à x * 2 ^ 32 = 0 (mod 2 ^ 32). La séquence des puissances de deux est liée aux codes Gray (entre autres) et apparaît sous la forme https://oeis.org/A001511 .

EDIT: pour voir pourquoi les autres réponses à cette question sont incomplètes, considérez le fait que le même programme, limité aux entiers impairs uniquement, ferait pas converger vers 0, malgré tout le débordement.

70
user295691

Cela ressemble à un débordement d'entier .

Regarde ça

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

Sortie:

25977982938941930515945176761070443325092850981258133993315252362474391176210383043658995147728530422794328291965962468114563072000000000000000000000

La sortie ne sera plus une valeur int. Vous obtiendrez alors une valeur erronée à cause du débordement.

S'il déborde, il retourne à la valeur minimale et continue à partir de là. Si le débit est insuffisant, il revient à la valeur maximale et continue à partir de là.

Plus info

Éditez .

Changeons ton code comme suit

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

Out mis:

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
34

C'est à cause d'un débordement d'entier. Lorsque vous multipliez plusieurs nombres pairs, le nombre binaire génère beaucoup de zéros. Quand vous avez plus de 32 zéros à la fin d'un int, il retourne à 0.

Pour vous aider à visualiser ceci, voici les multiplications en hexa calculées sur un type de nombre qui ne débordera pas. Voyez comment les zéros à la fin croissent lentement et notez qu'un int est composé des 8 derniers chiffres hexadécimaux. Après avoir multiplié par 42 (0x2A), les 32 bits d'un int sont des zéros!

                                     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
Tim S.

Quelque part au milieu, vous obtenez 0 en tant que produit. Ainsi, votre produit entier sera 0.

Dans ton cas :

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

Chaque fois que vous multipliez la valeur actuelle de i par le nombre obtenu, vous obtenez 0 en sortie.

14
TheLostMind

Étant donné que bon nombre des réponses existantes pointent vers les détails d'implémentation de Java et la sortie de débogage, examinons le calcul derrière la multiplication binaire pour vraiment répondre au pourquoi.

Le commentaire de @kasperd va dans la bonne direction. Supposons que vous ne multipliez pas directement avec le nombre mais avec les facteurs premiers de ce nombre. Beaucoup de nombres auront 2 comme facteur premier. En binaire, cela équivaut à un décalage à gauche. Par commutativité, nous pouvons multiplier par 2. Cela signifie que nous faisons juste un changement à gauche.

Lorsque vous examinez les règles de multiplication binaires, le seul cas où un 1 aboutira à une position de chiffre spécifique est lorsque les deux valeurs d'opérande sont égales à un.

Ainsi, l'effet d'un décalage à gauche est que la position de bit la plus basse d'un 1 lorsque l'on multiplie davantage le résultat est augmentée.

Puisque entier ne contient que les bits de poids faible, ils seront tous mis à 0 lorsque le facteur premier 2 sera suffisamment pris en compte dans le résultat.

Notez que la représentation du complément à deux n'est pas intéressante pour cette analyse, car le signe du résultat de la multiplication peut être calculé indépendamment du nombre résultant. Cela signifie que si la valeur déborde et devient négative, les bits de poids faible sont représentés par 1, mais lors de la multiplication, ils sont traités à nouveau comme étant 0.

12
SpaceTrucker

Si je lance ce code Ce que je reçois tous -

          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

Cause de débordement d'entier -

980179200 * 18 =   463356416 (should be 17643225600)

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

Produire 0 cause -

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

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

Finalement, le calcul déborde, et finalement ce débordement conduit à un produit de zéro; cela arrive quand product == -2147483648 et i == 42. Essayez ce code pour le vérifier par vous-même (ou exécutez le code ici ):

import Java.math.BigInteger;

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

Une fois que c'est zéro, il reste bien sûr zéro. Voici un code qui produira un résultat plus précis (vous pouvez exécuter le code ici ):

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

C'est un débordement d'entier.

Le type de données int est 4 octets ou 32 bits. Par conséquent, les nombres supérieurs à 2 ^ (32 - 1) - 1 (2 147 483 647) ne peuvent pas être stockés dans ce type de données. Vos valeurs numériques seront incorrectes.

Pour les très grands nombres, vous voudrez importer et utiliser la classe 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());

REMARQUE: pour les valeurs numériques encore trop grandes pour le type de données int, mais suffisamment petites pour tenir dans 8 octets (valeur absolue inférieure ou égale à 2 ^ (64 - 1) - 1), vous devez probablement utiliser le paramètre long primitive.

Les problèmes de pratique de HackerRank (www.hackerrank.com), tels que la section pratique des algorithmes, ( https://www.hackerrank.com/domains/algorithms/warmup ) incluent de très bonnes questions à grand nombre qui donnent une bonne pratique sur la manière de réfléchir au type de données approprié à utiliser.

1
La-comadreja