J'essaie de représenter le numéro de port 9876 (ou 0x2694 en hex) dans un tableau de deux octets: mais je reçois un avertissement sur une perte de précision possible: p > Comment puis-je représenter le numéro 9876 dans un tableau de deux octets sans perdre de précision? p> Note: strong> J'ai sélectionné le code par @ Björn comme réponse correcte, mais le code de @glowcoder fonctionne également bien. C'est juste une approche différente du même problème. Merci à tous! P> p>
7 Réponses :
Avez-vous essayé de jeter à un octet? E.G.
sendData[1] = (byte)0x94;
Cela me fera perdre de la précision, n'est-ce pas?
@Mark: Cela fera clairement le compilateur que vous faites exactement ce que vous voulez faire. 0x94 se trouve dans la plage d'un octet, il n'y a donc aucune perte réelle de précision ici.
Non, ce n'est pas dans la plage d'un octet. Tout dans Java est signé et 0x94 est lu comme un int, et a été lancé à un octet.
Je pensais que la gamme d'un octet était de -128 à 127 et 0x94 est 148
@Mark - 0x94 En tant que octet n'est pas en réalité 148, c'est -108.
@Mark: Eh bien ... non. En regardant les bits, la gamme d'un octet est de 0B00000000 à 0B11111111 et 0x94 = 0B10010100, qui est correctement dans sa plage. Bitwise, le concept "Signé Byte" n'a aucun sens. Ce n'est que lorsque vous interprétez une séquence de huit bits comme un entier qu'il commence à être clair.
Vous devez vous lancer en (octet) comme type de numéro par défaut dans Java est INT, ce qui est plus grand que l'octet. Tant que la valeur s'adapte à l'octet, il est correct de lancer. P>
Essayez ceci: ou ceci: p> Vous devez lancer des données en octet afin de l'attribuer à un octet! p> qui ne signifie pas que vous avez perdu la précision, il suffit d'écrire mais également note: la plage d'un octet est de -128 à 127, donc en cas de 0x26 code> signifie un compilateur INT vers Java. p>
0x94 = 148 code>, il sera représenté après la coulée d'octet comme "-108", de sorte qu'il ne fonctionnera pas correctement dans des calculs mathématiques. P> P> P> p >
C'est parce que tout en Java est signé. 0x94 (148) est supérieur à l'octet.max_value (2 ^ 7-1).
Ce dont vous avez besoin est P>
public static byte[] intToByteArray(int value) { byte[] b = new byte[4]; for (int i = 0; i < 4; i++) { int offset = (b.length - 1 - i) * 8; b[i] = (byte) ((value >>> offset) & 0xFF); } return b; }
Remarque, cela fait tous les 4 octets de l'int ... vous n'avez besoin que de deux d'entre eux. Le reste est simple à partir de cela.
C'est deux mal - ce n'est pas parce que tout est signé, c'est parce que 0x94 est un int, pas un octet, et d'autre part, le type de caractère n'est pas signé, et troisième - est ce code une blague? Si vous ne faites que jouer avec le gars, cela vaut peut-être un +1 :) L'original allait bien si vous avez baissé le (octet)
0x94 est un int car il ne s'intègre pas dans un octet car les octets sont signés code>. Vous êtes correct que les caractères sont non signés - cependant, c'est l'exception à la règle, car ce n'est pas un code> destiné à être un nombre - le Javagods a décidé que tous leurs numéros seront signés. Pouvez-vous l'utiliser comme un numéro d'optimisation des chaînes? Oui, vous pouvez. Était-ce l'intention d'être utilisé comme numéro? Non. Le
Caractère CODE> Étendez-vous le numéro
NUMÉRO CODE> CLASSE? N ° troisième, non ce code n'est pas une blague, c'est une façon légitime de convertir n'importe quel Int vers un tableau d'octets pour représenter avec précision ses bits. Je l'ai utilisé pour la création de paquets TCP / IP dans le passé.
J'ai essayé votre code et ça marche très bien. Merci d'avoir aidé un débutant à apprendre Java!
0x94 est de 148 en décimal, qui dépasse la gamme d'octets en Java (-128 à 127). Vous pouvez faire l'une des opérations suivantes:
1) Une distribution fonctionnera bien car elle préservera la représentation binaire (aucun bits significatifs n'est tronqué pour 0x00 à 0XFF): P>
sendData[1] = -0x6C; //or -108 in decimal
Et pour reconvertir l'octet signé en son formulaire Int non signé, vous pouvez simplement écrire B & 0XFF code>.
Ma première réponse serait bossée, mais à une seconde pensée, je pense que l'utilisation de sorties de sortie pourrait être meilleure et plus simple à comprendre. J'évite habituellement le casting, mais si vous n'allez pas pour une solution générique, je suppose que cela irait bien. :)
Utilisation de flux, une solution générique: p> et pour l'inverser: p> public int byteArrayToInt(final byte[] b) throws IOException {
java.io.ByteArrayInputStream ba = new java.io.ByteArrayInputStream(b);
java.io.DataInputStream d = new java.io.DataInputStream(ba);
return d.readInt();
}
Vous pouvez également le faire de manière générique avec Java.nio.Bytebuffer et contrôler également l'endianess si nécessaire. J'ai ajouté une réponse pour cette possibilité.
Björn a donné une bonne réponse générique avec l'utilisation de flux. Vous pouvez également faire cette même chose avec Pour créer le tableau d'octets: < / p> pour inverser: p> java.nio.bytebuffer code> qui entraîne un code légèrement moins de code et vous pouvez également contrôler l'endianess (ordre d'octets) de la sortie.
Notez que l'aplatissement des structures de données pour l'envoi du fil est généralement effectuée avec un dataOutputStream (ou son objectif de sous-classe d'obtuprputstream) en Java. Pas besoin de réinventer le bitfidling à chaque fois :-)
@meriton: Et mieux encore, utilisez
java.nio.bytebuffer code> qui peut faire tout cela, il n'est pas nécessaire de gérer l'ioException et de contrôler l'endansion.