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);
}
}
Quelqu'un peut-il expliquer pourquoi cela se produit?
java
integer
integer-overflow
Aniruddha Sarkar
la source
la source
2
environ 90 fois. Cela signifie que vous aurez besoin d'une variable d'au moins 90 bits pour obtenir une sortie non nulle. 32 et 64 sont tous deux inférieurs à 90. Afin de calculer des entiers plus grands que les mots natifs, vous devez utiliser la grande classe d'entiers disponible dans la langue choisie.Réponses:
Voici ce que fait le programme à chaque étape:
Notez que sur certaines étapes, la multiplication entraîne un nombre plus petit (980179200 * 18 = 463356416) ou un signe incorrect (213837312 * 20 = -18221056), indiquant qu'il y a eu un dépassement d'entier. Mais d'où vient le zéro? Continuer à lire.
En gardant à l'esprit que
int
le type de données est un entier 32 bits signé , complément à deux , voici une explication de chaque étape:Nous savons que multiplier un nombre par un nombre pair:
Donc, fondamentalement, votre programme multiplie un nombre pair avec un autre nombre à plusieurs reprises, ce qui remet à zéro les bits de résultat en commençant par la droite.
PS: Si les multiplications n'impliquent que des nombres impairs, le résultat ne deviendra pas nul.
la source
La multiplication des ordinateurs se produit vraiment modulo 2 ^ 32. Une fois que vous avez accumulé suffisamment de puissances de deux dans le multiplicande, toutes les valeurs seront 0.
Ici, nous avons 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
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, restreint aux entiers impairs uniquement, ne convergerait pas vers 0, malgré tout le débordement.
la source
Cela ressemble à un débordement d'entier .
Regarde ça
Production:
La sortie n'est plus une
int
valeur. Ensuite, vous obtiendrez une valeur erronée à cause du débordement.Plus d' info
Modifier .
Modifions votre code comme suit
Production:
la source
C'est à cause d'un débordement d'entier. Lorsque vous multipliez plusieurs nombres pairs ensemble, le nombre binaire obtient beaucoup de zéros de fin. Lorsque vous avez plus de 32 zéros de fin pour un
int
, il passe à0
.Pour vous aider à visualiser cela, voici les multiplications en hexadécimal calculées sur un type de nombre qui ne débordera pas. Voyez comment les zéros de fin grandissent lentement et notez que an
int
est composé des 8 derniers chiffres hexadécimaux. Après avoir multiplié par 42 (0x2A), les 32 bits de anint
sont des zéros!la source
Quelque part au milieu, vous obtenez
0
le produit. Ainsi, votre produit entier sera 0.Dans ton cas :
Chaque fois que vous multipliez la valeur actuelle de
i
par le nombre que vous obtenez0
en sortie.la source
Étant donné que la plupart des réponses existantes pointent vers les détails d'implémentation de Java et la sortie de débogage, examinons les mathématiques derrière la multiplication binaire pour vraiment répondre au pourquoi.
Le commentaire de @kasperd va dans le bon sens. Supposons que vous ne multipliez pas directement avec le nombre mais avec les facteurs premiers de ce nombre à la place. De nombreux nombres auront 2 comme facteur premier. En binaire, cela équivaut à un décalage vers la gauche. Par commutativité, nous pouvons multiplier par des facteurs premiers de 2 en premier. Cela signifie que nous faisons juste un décalage vers la gauche.
En examinant les règles de multiplication binaire, le seul cas où un 1 entraînera une position de chiffre spécifique est lorsque les deux valeurs d'opérande sont une.
Ainsi, l'effet d'un décalage vers la gauche est que la position de bit la plus basse d'un 1 lors de la multiplication supplémentaire du résultat est augmentée.
Puisque l'entier ne contient que les bits d'ordre le plus bas, ils seront tous mis à 0 lorsque le facteur premier 2 est assez souvent inclus 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 à nouveau traités comme étant 0.
la source
Si j'exécute ce code, ce que j'obtiens tout -
Cause de dépassement d'entier -
Produire 0 cause -
la source
Finalement, le calcul déborde, et finalement ce débordement conduit à un produit de zéro; cela arrive quand
product == -2147483648
eti == 42
. Essayez ce code pour le vérifier par vous-même (ou exécutez le code ici ):Une fois qu'il est nul, il reste bien sûr nul. Voici un code qui produira un résultat plus précis (vous pouvez exécuter le code ici ):
la source
C'est un débordement d'entier.
Le type de données int est de 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:
REMARQUE: Pour les valeurs numériques qui sont 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 devriez probablement utiliser la
long
primitive.Les problèmes de pratique de HackerRank (www.hackerrank.com), tels que la section de pratique des algorithmes ( https://www.hackerrank.com/domains/algorithms/warmup ) incluent de très bonnes questions en grand nombre qui donnent de bonnes pratiques sur la façon de pensez au type de données approprié à utiliser.
la source