2010-02-25 11 views
0

D'accord au niveau du bit, donc j'ai 4 entiers Je veux envelopper dans une longue. Les 4 entiers tous contient 3 valeurs, positionnées dans les 2 premiers octets:Emballage 4 entiers dans un 64 peu long - java

+--------+--------+ 
|xxpppppp|hdcsrrrr| 
+--------+--------+ 

{pppppp} représente une valeur, {HDCS} représente la deuxième et {} rrrr dernier.

Je veux emballer 4 de ces entiers, dans une longue. Je l'ai essayé ce qui suit:

ordinal = (c1.ordinal() << (14*3) | c2.ordinal() << (14*2) | c3.ordinal() << 14 | c4.ordinal()); 

où c1.ordinal() ... c4.ordinal() sont les entiers pour envelopper.

Cela ne semble pas fonctionner si je lance un test. Disons que je veux regarder les valeurs du dernier entier long, c4.ordinal(), où {pppppp} = 41, {HDCS} = 8 et {rrrr} = 14, je reçois les résultats suivants:

System.out.println(c4.ordinal() & 0xf); //Prints 14 
System.out.println(hand.ordinal() & 0xf); // Prints 14 - correct 

System.out.println(c4.ordinal() >> 4 & 0xf); // Prints 8 
System.out.println(hand.ordinal() >> 4 & 0xf); // Prints 8 - correct 

System.out.println(c4.ordinal() >> 8 & 0x3f); // Prints 41 
System.out.println(hand.ordinal() >> 8 & 0x3f); // Prints 61 - NOT correct! 

Maintenant, ce qui suit est bizarre pour moi. Si je retire les deux premiers entiers, et seulement envelopper les deux derniers, comme ceci:

ordinal = (c3.ordinal() << 14 | c4.ordinal()); 

et exécutez le même test, j'obtenir le résultat correct:

System.out.println(c4.ordinal() >> 8 & 0x3f); // Prints 41 
System.out.println(hand.ordinal() >> 8 & 0x3f); // Prints 41 - correct! 

Je ne sais pas ce qui est erroné . Et cela n'a aucun sens pour moi, que j'obtiens la bonne réponse si j'enlève les deux premiers entiers. Je commence à penser que cela pourrait avoir à faire avec le type de données long, mais je n'ai encore rien trouvé, qui supporte cette théorie.

+0

@Frederik: Pourquoi vous déplacez-vous par multiples de 14 et vous déplacez par multiples de 4? – Welbog

+0

Parce que les deux derniers bits des valeurs de 16 bits, sera toujours 0, donc ils n'ont pas d'importance. 2 des 3 valeurs ont une longueur de 4 bits, donc je change de 4 à chaque fois. (Le dernier est long de 6 bits, donc j'ai besoin d'utiliser un autre masque pour cette valeur). –

Répondre

6

Même si vous attribuez le résultat à long, toutes les opérations sont exécutées avec des valeurs int et les bits de poids fort sont perdus. Forcer "promotion" à long en explicitement élargir les valeurs à un long.

long ordinal = (long) c1.ordinal() << (14*3) | 
       (long) c2.ordinal() << (14*2) | 
       (long) c3.ordinal() << 14 | 
       (long) c4.ordinal(); 

De plus, à moins que vous êtes certain que les deux bits supérieurs de chaque valeur sont égales à zéro, vous pouvez exécuter d'autres problèmes. Vous pouvez les masquer pour des raisons de sécurité:

long ordinal = (c1.ordinal() & 0x3FFFL) << (14*3) | 
       (c2.ordinal() & 0x3FFFL) << (14*2) | 
       (c3.ordinal() & 0x3FFFL) << 14 | 
       (c4.ordinal() & 0x3FFFL); 
+0

Vous êtes génial! Merci :) –

+0

Est-ce une connaissance commune? Sun ne mentionne pas vraiment cela partout où je suis tombé ... –

+0

À peu près - et ce n'est pas spécifique à Java. Lorsque vous travaillez sur des opérateurs avec un type et que vous les attribuez à un type différent, vous devez généralement convertir le type de source avant tout calcul ... Ceci est plus logique en tant qu'exemple simple, qui peut être java, C ou C++: int x1 = 1; int x2 = 2; flotteur y = x1/x2; y == 0 flotteur z = ((float) x1)/((float) x2); z == 0.5f (ack, les commentaires ne sont pas des sauts de ligne) – CuriousPanda