Question 2 'complémente le nombre hexadécimal en décimal en Java


J'ai une chaîne hexadécimale qui représente un nombre de complément à 2. Existe-t-il un moyen simple (bibliothèques / fonctions) de traduire l'hexagone en un nombre décimal sans travailler directement avec ses bits?

PAR EXEMPLE. C'est la sortie attendue étant donné l'hexagone à gauche:

"0000" => 0
"7FFF" => 32767 (max positive number)
"8000" => -32768 (max negative number)
"FFFF" => -1

Merci!


12
2017-07-14 20:04


origine


Réponses:


Cela semble tromper Java en convertissant le nombre sans forcer un résultat positif:

Integer.valueOf("FFFF",16).shortValue(); // evaluates to -1 (short)

Bien sûr, ce genre de chose ne fonctionne que pour les 8, 16, 32 et 64 bits 2:

Short.valueOf("FF",16).byteValue(); // -1 (byte)
Integer.valueOf("FFFF",16).shortValue(); // -1 (short)
Long.valueOf("FFFFFFFF",16).intValue(); // -1 (int)
new BigInteger("FFFFFFFFFFFFFFFF",16).longValue(); // -1 (long)

Exemple ici.


17
2017-07-14 20:45



Écrivez simplement une méthode utilitaire:

 public static Integer twosComp(String str) throws java.lang.Exception {
       Integer num = Integer.valueOf(str, 16);
       return (num > 32767) ? num - 65536 : num;
 }

Tests:

 twosComp("7FFF") -> 32767
 twosComp("8000") -> -32768
 twosComp("FFFF") -> -1

8
2017-07-14 20:08



Cela semble fonctionner raisonnablement bien. On peut le tromper en lui passant des chaînes de longueur non standard: "FFF" correspond à -1. Le remplissage zéro corrige le défaut.

Vous ne savez pas sur quel type de retour vous voulez, alors je suis revenu Number, quelle que soit la taille est appropriée.

public Number hexToDec(String hex)  {
   if (hex == null) {
      throw new NullPointerException("hexToDec: hex String is null.");
   }

   // You may want to do something different with the empty string.
   if (hex.equals("")) { return Byte.valueOf("0"); }

   // If you want to pad "FFF" to "0FFF" do it here.

   hex = hex.toUpperCase();

   // Check if high bit is set.
   boolean isNegative =
      hex.startsWith("8") || hex.startsWith("9") ||
      hex.startsWith("A") || hex.startsWith("B") ||
      hex.startsWith("C") || hex.startsWith("D") ||
      hex.startsWith("E") || hex.startsWith("F");

   BigInteger temp;

   if (isNegative) {
      // Negative number
      temp = new BigInteger(hex, 16);
      BigInteger subtrahend = BigInteger.ONE.shiftLeft(hex.length() * 4);
      temp = temp.subtract(subtrahend);
   } else {
      // Positive number
      temp = new BigInteger(hex, 16);
   }

   // Cut BigInteger down to size.
   if (hex.length() <= 2) { return (Byte)temp.byteValue(); }
   if (hex.length() <= 4) { return (Short)temp.shortValue(); }
   if (hex.length() <= 8) { return (Integer)temp.intValue(); }
   if (hex.length() <= 16) { return (Long)temp.longValue(); }
   return temp;
}

Sortie de l'échantillon:

"33" -> 51
"FB" -> -5
"3333" -> 13107
"FFFC" -> -4
"33333333" -> 53687091
"FFFFFFFD" -> -3
"3333333333333333" -> 3689348814741910323
"FFFFFFFFFFFFFFFE" -> -2
"33333333333333333333" -> 241785163922925834941235
"FFFFFFFFFFFFFFFFFFFF" -> -1

3
2017-07-14 22:32