int i =132;
byte b =(byte)i; System.out.println(b);
Époustouflant. Pourquoi la sortie -124
?
En Java, an int
vaut 32 bits. A byte
est 8bits
.
La plupart des types primitifs en Java sont signés, et byte
, short
, int
et long
sont codés en complément à deux. (Le char
type n'est pas signé et le concept de signe n'est pas applicable àboolean
.)
Dans ce schéma numérique, le bit le plus significatif spécifie le signe du nombre. Si plus de bits sont nécessaires, le bit le plus significatif ("MSB") est simplement copié dans le nouveau MSB.
Donc, si vous avez byte 255
: 11111111
et que vous voulez le représenter comme un int
(32 bits), vous copiez simplement le 1 vers la gauche 24 fois.
Maintenant, une façon de lire un nombre de complément à deux négatifs est de commencer par le bit le moins significatif, de se déplacer vers la gauche jusqu'à ce que vous trouviez le premier 1, puis d'inverser chaque bit par la suite. Le nombre résultant est la version positive de ce nombre
Par exemple: 11111111
va à 00000001
=-1
. C'est ce que Java affichera comme valeur.
Ce que vous voulez probablement faire est de connaître la valeur non signée de l'octet.
Vous pouvez accomplir cela avec un masque de bits qui supprime tout sauf les 8 bits les moins significatifs. (0xff)
Alors:
byte signedByte = -1;
int unsignedByte = signedByte & (0xff);
System.out.println("Signed: " + signedByte + " Unsigned: " + unsignedByte);
Imprimera: "Signed: -1 Unsigned: 255"
Que se passe-t-il réellement ici?
Nous utilisons ET au niveau du bit pour masquer tous les bits de signe superflus (les 1 à gauche des 8 bits les moins significatifs.) Lorsqu'un entier est converti en octet, Java coupe les 24 bits les plus à gauche.
1111111111111111111111111010101
&
0000000000000000000000001111111
=
0000000000000000000000001010101
Puisque le 32ème bit est maintenant le bit de signe au lieu du 8ème bit (et que nous mettons le bit de signe à 0, ce qui est positif), les 8 bits d'origine de l'octet sont lus par Java comme une valeur positive.
signedByte & (0xff)
se passe ici est qu'il0xff
s'agit d'un littéral entier, donc signedByte est promu en entier avant que l'opération au niveau du bit ne soit effectuée.132
en chiffres ( base 10 ) est1000_0100
en bits ( base 2 ) et Java stockeint
en 32 bits:L'algorithme pour int-to-byte est tronqué à gauche; L'algorithme pour
System.out.println
est un complément à deux (le complément à deux est si le bit le plus à gauche est1
, interprété comme un complément à un négatif (bits inversés ) moins un.); AinsiSystem.out.println(int-to-byte(
))
est:0000_0000_0000_0000_0000_0000_1000_0100
) [)))])1000_0100
[)))])1000_0100
))))1000_0011
)))0111_1100
))la source
0
pour le positif et1
pour le négatif).int
en abyte
est une conversion avec perte (c'est-à-dire que l'information est perdue). Par conséquent, il n'existe aucun moyen de le reconvertir dans saint
valeur d' origine .l'octet en Java est signé, il a donc une plage de -2 ^ 7 à 2 ^ 7-1 - c'est-à-dire de -128 à 127. Puisque 132 est au-dessus de 127, vous finissez par revenir à 132-256 = -124. Autrement dit, essentiellement 256 (2 ^ 8) sont ajoutés ou soustraits jusqu'à ce qu'ils tombent dans la plage.
Pour plus d'informations, vous pouvez consulter le complément à deux .
la source
132 est en dehors de la plage d'un octet qui est de -128 à 127 (Byte.MIN_VALUE à Byte.MAX_VALUE) Au lieu de cela, le bit supérieur de la valeur 8 bits est traité comme le signe qui indique qu'il est négatif dans ce cas. Donc, le nombre est 132 - 256 = -124.
la source
voici une méthode très mécanique sans les théories distrayantes:
Cette méthode plus pratique est conforme aux réponses très théoriques ci-dessus. Donc, ceux qui lisent encore ces livres Java disant d'utiliser modulo, c'est définitivement faux car les 4 étapes que j'ai décrites ci-dessus ne sont certainement pas une opération modulo.
la source
http://iiti.ac.in/people/~tanimad/JavaTheCompleteReference.pdf
page 59Équation du complément à deux:
En Java,
byte
(N = 8) etint
(N = 32) sont représentés par le complément 2s illustré ci-dessus.D'après l'équation, un 7 est négatif pour
byte
mais positif pourint
.la source
souvent dans les livres, vous trouverez l'explication du transtypage d'un entier à un octet comme étant effectué par division de module. ce n'est pas strictement correct comme indiqué ci-dessous ce qui se passe réellement est que les 24 bits les plus significatifs de la valeur binaire du nombre int sont rejetés, laissant une confusion si le bit le plus à gauche restant est défini, ce qui désigne le nombre comme négatif
la source
Un algorithme rapide qui simule la façon dont cela fonctionne est le suivant:
Comment ça marche? Regardez la réponse de daixtr . Une implémentation de l'algorithme exact décrit dans sa réponse est la suivante:
la source
Si vous voulez comprendre cela mathématiquement, comme comment cela fonctionne
donc fondamentalement les nombres b / w -128 à 127 seront écrits de la même manière que leur valeur décimale, au-dessus de cela (votre nombre - 256).
par exemple. 132, la réponse sera 132 - 256 = - 124 ie
256 + votre réponse au nombre 256 + (-124) est 132
Un autre exemple
la sortie sera 39 44
(295 à 256) (300 à 256)
REMARQUE: il ne tiendra pas compte des nombres après la virgule.
la source
Conceptuellement, des soustractions répétées de 256 sont faites à votre nombre, jusqu'à ce qu'il soit compris entre -128 et +127. Donc, dans votre cas, vous commencez par 132, puis vous terminez par -124 en une seule étape.
Sur le plan informatique, cela correspond à l'extraction des 8 bits les moins significatifs de votre numéro d'origine. (Et notez que le bit le plus significatif de ces 8 devient le bit de signe.)
Notez que dans d'autres langages, ce comportement n'est pas défini (par exemple C et C ++).
la source
la source