Pourquoi ne i = i + je me donne 0?
J'ai un programme simple:
public class Mathz {
static int i = 1;
public static void main(String[] args) {
while (true){
i = i + i;
System.out.println(i);
}
}
}
Quand je lance ce programme, tout ce que je vois est 0
pour i
dans ma sortie. Je me serais attendu le premier tour, nous aurions i = 1 + 1
, suivie par i = 2 + 2
, suivie par i = 4 + 4
etc.
Est-ce dû au fait que dès que l'on essaie de re-déclarer i
sur la gauche, sa valeur est remis à 0
?
Si quelqu'un peut me pointer dans les détails de ce qui serait formidable.
Changer le int
à long
et il semble être l'impression de numéros comme prévu. Je suis surpris de voir à quelle vitesse il frappe le max valeur de 32 bits!
Vous devez vous connecter pour publier un commentaire.
Le problème est dû à débordement d'entier.
En 32-bit des deux-complément de l'arithmétique:
i
, en effet, de commencer à avoir une puissance de deux valeurs, mais alors débordement de comportements commencer une fois que vous obtenez à 230:...dans
int
arithmétique, puisque c'est essentiellement l'arithmétique mod 2^32.int
.int
àlong
.long
ne peut même représenter des nombres >= 2^63.0
sur les premières itérations, mais la vitesse de sortie est occulter le fait de l'OP). Pourquoi est-elle acceptée?Introduction
Le problème de dépassement d'entier. S'il déborde, il va revenir à la valeur minimale et continue à partir de là. Si il underflows, il va revenir à la valeur maximale et continue à partir de là. L'image ci-dessous est un compteur kilométrique. Je l'utilise pour expliquer les débordements. C'est une mécanique de débordement, mais un bon exemple encore.
Dans un Odomètre, le
max digit = 9
, afin d'aller au-delà du maximum de moyens9 + 1
, qui transporte plus et donne un0
; Cependant, il n'est pas plus élevé chiffres de changer pour une1
, de sorte que le compteur est remis à zéro àzero
. Vous avez l'idée - "débordements d'entiers" viennent à l'esprit maintenant.Ainsi,
2147483647 + 1
déborde et s'enroule autour de-2147483648
. Doncint i=2147483647 + 1
serait débordé, ce qui n'est pas égal à2147483648
. Aussi, dites-vous "c'est toujours affiche "0". Il ne le fait pas, parce que http://ideone.com/WHrQIW. Ci-dessous, ces 8 chiffres montrent que le point auquel il pivots et les débordements. Il commence alors à imprimer 0s. Aussi, ne soyez pas surpris comment rapidement il calcule, les machines d'aujourd'hui sont rapides.Pourquoi débordement d'entier ", s'enroule autour de"
PDF Original
<sup></sup>
balises.Non, il n'imprime pas uniquement des zéros.
Changer à cela et vous verrez ce qui se passe.
Ce qui se passe est appelé débordement.
true
aveci<10000
🙂while(k --> 0)
familièrement nommé "alors quek
va à0
" 😉sortie:
Puisque je n'ai pas assez de réputation, je ne peut pas publier la photo de la sortie pour le même programme en C avec contrôle de la sortie, u pouvez essayer vous-même et de voir qu'il fait des tirages 32 fois et ensuite comme expliqué en raison de dépassement de i=1073741824 + 1073741824 les modifications apportées à
-2147483648 et une plus de plus de plus est hors de portée de l'int et devient Zéro .
system("deltree C:")
, puisque vous êtes sous DOS/Windows). Signé débordement d'entier est un comportement indéfini en C/C++, contrairement à Java. Être très prudent lors de l'utilisation de ce genre de construction.signed and unsigned
entiers sans undefined behaviori += i
pour 32+ itérations, puis avaitif (i > 0)
. Le compilateur peut optimiser que deif(true)
car si nous sommes toujours à l'ajout de nombres positifs,i
sera toujours plus grand que 0. Il pourrait aussi laisser à l'état, où il ne sera pas exécuté, en raison du trop-plein représenté ici. Parce que le compilateur peut produire deux tout aussi valide les programmes de ce code, c'est un comportement indéterminé.La valeur de
i
est stockée dans la mémoire à l'aide d'une quantité fixe de chiffres binaires. Quand un certain nombre de besoins de plus de chiffres sont disponibles, les chiffres les plus bas sont enregistrés (les chiffres les plus élevés se perdre).Ajoutant
i
à lui-même est le même que multiplianti
par deux. Tout comme la multiplication d'un nombre par dix en notation décimale peut être effectuée en faisant glisser chaque chiffre à la gauche et de mettre un zéro à droite, la multiplication d'un nombre par deux en notation binaire peut être effectué de la même façon. Cela ajoute un chiffre sur la droite, si un chiffre est perdu sur la gauche.Ici la valeur de départ est 1, donc, si nous utilisons des 8 chiffres pour stocker
i
(par exemple),00000001
00000010
00000100
et ainsi de suite, jusqu'à la finale de la non-zéro étape
10000000
00000000
Peu importe le nombre de chiffres binaires sont alloués pour stocker le nombre, et quelle que soit la valeur de départ est, finalement, tous les chiffres seront perdus car ils sont poussés vers la gauche. Après cela, continuer à doubler le nombre ne changera pas le nombre, il sera toujours représenté par tous les zéros.
C'est correct, mais après le 31 itérations, 1073741824 + 1073741824 ne parvient pas à calculer correctement et après qui n'imprime que des 0.
Vous pouvez restructurer à utiliser BigInteger, de sorte que votre boucle infinie fonctionne correctement.
int
.long
peut représenter un plus grand nombre deint
peut.Pour le débogage de tels cas, il est judicieux de réduire le nombre d'itérations dans la boucle. Utiliser ce lieu de votre
while(true)
:Vous pouvez alors voir qu'il commence par 2 et le doublement de la valeur jusqu'à ce qu'il est à l'origine d'un dépassement de capacité.
Je vais utiliser un nombre de 8 bits pour l'illustration, car il peut être complètement détaillé dans un court espace. Les nombres hexadécimaux commence par 0x, tandis que les nombres binaires commencer avec 0b.
La valeur maximale d'un entier 8 bits non signé est de 255 (0xFF ou 0b11111111).
Si vous ajoutez 1, vous auriez normalement s'attendre à obtenir: 256 (0x100) ou 0b100000000).
Mais puisque c'est le trop grand nombre de bits (9), qui est au-dessus du max, de sorte que la première partie tout est perdu, vous laissant avec 0 efficacement (0x(1)00 ou 0b(1)00000000, mais avec le 1 chute).
Ainsi, lorsque votre programme s'exécute, vous obtenez:
Le plus grand décimal littéral de type
int
est 2147483648 (=231). Toutes les décimales des littéraux de de 0 à 2147483647 peut apparaître n'importe où int littérale peut apparaître, mais le littéral 2147483648 peut apparaître que comme l'opérande de l'opérateur de négation unaire -.Si un nombre entier plus les débordements, alors le résultat est bits de mathématiques de la somme représentée dans certaines suffisamment grand complément à deux format. Si le dépassement se produit, alors le signe du résultat est pas le même que le signe de la mathématique somme des deux opérande valeurs.