2017-02-15 1 views
-1

J'ai quelque chose comme ceci:Convertir les données 64bit à valeur signée à long

byte[0] = 0001 0100 0011 0100 (dec value: 5172) 
byte[1] = 0000 0000 0111 1100 (dec value: 124) 
byte[2] = 0000 0000 0000 0000 (dec value: 0) 
byte[3] = 0000 0000 0000 0000 (dec value: 0) 

Je voudrais les combiner et faire une longue valeur en Java. Comment faire ça?

Peut-il être converti de cette façon?

résultat = 0 + (0 x 2^16) + (0 x 2^16) + (124 x 32^2) + (5127 x 2^48)

ie.

result = octet [3] + (byte [2] x 2^16) + (byte [1] x 2^32) + (octet [0] x 2^48)

Edit: Soit J'essaie d'expliquer mieux. Quand j'ouvre l'outil ModScan32 et que je me connecte à mon appareil, je vois des registres. Dans cet outil, il existe différents types d'options pour afficher les données. L'un d'eux est de les représenter comme binaires ou décimaux. Quand je choisis binaire ou décimal, j'obtiens des valeurs comme dans mon exemple ci-dessus. Quand je lis ces données avec mon logiciel, j'obtiens exactement la même chose (valeurs converties) dans la décimale. Maintenant, ma question est de savoir s'il est nécessaire de conserver les données dans 4 registres de 16 bits et je connais leurs valeurs décimales. Quelle est la bonne façon de combiner ces valeurs des registres et d'obtenir une valeur réelle?

+0

Je ne comprends pas vraiment comment vos valeurs sont stockées, mais si vous connaissez les valeurs décimales, pourquoi ne pas les écrire? Sinon, considérez built-int Long.parseLong méthodes –

+0

Les valeurs lorsque je les lis à partir de l'appareil, j'obtiens des valeurs décimales, comme dans l'exemple ci-dessus, chaque valeur dans l'appareil est stockée dans 4 registres 16bit donc j'ai besoin de convertir ces valeurs valeur. Je ne suis pas sûr de savoir comment faire ça. – Josef

+2

Vos octets sont 16 bits ?? Vérifiez s'il vous plaît. Il n'y a rien de tel que stocker la valeur 5172 dans une variable de type 'byte'. –

Répondre

1

Votre idée est fondamentalement OK. Il y a quelques choses à savoir.

Je crois que le résultat que vous recherchez dans votre cas est 0001010000110100000000000111110000000000000000000000000000000000.

est ici une tentative qui ne fonctionne pas:

int[] registers = { 5172, 124, 0, 0 }; 
    long result = registers[0] << 48 | registers[1] << 32 | registers[2] << 16 | registers[3]; 
    System.out.println(Long.toBinaryString(result)); 

<< 48 un moyen de décalage 48 bits vers la gauche, qui devrait être assez bon, non? | est un bit logique ou, il remplit les 1 bits de l'un ou l'autre opérande dans la même position de bit du résultat. Vous pouvez utiliser + à la place si vous préférez.

Cette impression:

10100001101000000000001111100 

Nous avons seulement les 32 premiers bits du résultat, ce n'est pas assez bon. Lorsque vous essayez de le lire, notez que Long.toBinaryString() n'inclut pas les zéros en tête. Imaginez juste 3 zéros devant le numéro.

Mais qu'est-ce qui s'est usé? Où sont passés les 32 derniers bits? Même quand ils étaient tous des zéros. Le problème est que nous faisons le calcul en int s, ils sont 32 bits, pas 64. EDIT: Mon explication précédente n'était pas entièrement correcte sur ce point. La vérité est la suivante: Lorsque vous faites << sur un int, seuls les 5 derniers bits de l'opérande droit sont pris en compte, donc puisque 48 est 110000 en binaire, seulement 10000 est utilisé, donc le décalage est le même que << 16. De même << 32 est le même que << 0, aucun changement du tout. Donc registers[0] et [1] ont fini dans la mauvaise position de bit. La solution est facile quand vous le savez: nous devons convertir en longavant faire le calcul.Maintenant, les derniers bits de l'opérande de droite sont utilisés, de sorte que 48 et 32 ​​sont comprises comme 48 et 32:

long result = ((long) registers[0]) << 48 | ((long) registers[1]) << 32 | registers[2] << 16 | registers[3]; 

Cette fois, nous obtenons

1010000110100000000000111110000000000000000000000000000000000 

Encore une fois, imaginez 3 zéro bits avant et tout est comme prévu.

Il y a une chose de plus. Disons que vous avez une valeur négative d'un registre, par exemple:

int[] registers = { 5172, -124, 0, 0 }; 

Le calcul qui vient travaillé nous donne maintenant

Cette fois-ci, il y a 64 bits imprimés, il est donc facile de voir il y a trop de 1 au début. Ils proviennent de la représentation int de -124. La solution est de les masquer:

int[] registers = { 5172, -124, 0, 0 }; 
    long result = ((long) registers[0] & 0xFFFF) << 48 
      | ((long) registers[1] & 0xFFFF) << 32 
      | (registers[2] & 0xFFFF) << 16 
      | (registers[3] & 0xFFFF); 
    System.out.println(Long.toBinaryString(result)); 

0xFFFF est de 16 1 bits, et & est le niveau du bit logique « et », donnant un bit 1 dans le résultat uniquement dans des positions où les deux opérandes ont un bit 1. Maintenant -124 masqué à 1111111110000100 obtient donc le résultat est le prévu:

1010000110100111111111000010000000000000000000000000000000000 

Cela devrait le faire.

+0

Merci pour votre explication détaillée. Cela m'a vraiment aidé à mieux comprendre. – Josef

+0

Glad vous avez aimé. Si vous voulez la vérité précise, s'il vous plaît noter ma correction de la façon dont «48» fonctionne. –