51 votes

Java : Soustraire '0' d'un char pour obtenir un int... pourquoi cela fonctionne-t-il ?

Cela fonctionne bien :

int foo = bar.charAt(1) - '0';

Pourtant, ce n'est pas le cas - car bar.charAt(x) renvoie un caractère :

int foo = bar.charAt(1);

Il semble qu'en soustrayant '0' du caractère, on le transforme en un nombre entier.

Pourquoi, ou comment, la soustraction de la chaîne '0' (ou est-ce un caractère ?) convertit-elle un autre caractère en un nombre entier ?

36 votes

Ne faites pas l'erreur de penser que '0' == 0 . En réalité, '0' == 48 .

2 votes

cliquez sur Ah, maintenant ça prend tout son sens ! Si seulement tu avais mis ça comme réponse et m'avais indiqué cs.utk.edu/~pham/ascii_table.jpg

0 votes

Ce cast implicite ne retourne pas la représentation décimale du caractère, comme @MarkPeters l'a souligné, donc si par exemple bar.charAt(1) retourne 'A', dont la représentation décimale est 65, int foo sera 17, 'A' - '0' = 65 - 48 = 17 et non 65.

48voto

Lukas Eder Points 48046

C'est une astuce intelligente. Les chars sont en fait du même type / longueur que les shorts. Si vous avez un caractère qui représente un chiffre ASCII/unicode (comme '1') et que vous lui soustrayez le plus petit chiffre ASCII/unicode possible (par exemple '0'), il vous restera la valeur correspondante du chiffre (donc 1).

Parce que char est identique à short (bien qu'il s'agisse d'un short non signé), vous pouvez le convertir en int en toute sécurité. Et la conversion est toujours effectuée automatiquement si l'arithmétique est impliquée.

4 votes

Les shorts peuvent avoir des valeurs négatives, mais pas les chars. De plus, il ne s'agit pas d'ASCII mais d'unicode (petite mais importante différence) : essayer int y = '\uffff' - '\ufffe';

0 votes

Vous avez raison. Pour les chiffres, les codes ASCII et Unicode coïncident, c'est pourquoi j'ai d'abord pensé à l'ASCII.

0 votes

C'est génial. J'ai eu besoin du commentaire de Mark Peter pour me rendre compte que par "valeur correspondante", vous voulez dire que je soustrais 48 de 49-57. De plus, l'erreur que j'obtenais était en fait une exception de type "array out of bounds" (tableau hors limites), donc ma question est peut-être trompeuse en disant que le premier exemple "ne fonctionne pas". Merci ! :)

17voto

DwB Points 14687

Il s'agit d'une vieille astuce ASCII qui fonctionne pour tout codage qui aligne les chiffres de '0' à '9' de manière séquentielle en commençant par '0'. En ASCII, "0" est un caractère de valeur 0x30 et "9" est 0x39. En résumé, si vous avez un caractère qui est un chiffre, la soustraction de "0" le "convertit" en sa valeur numérique.

Je dois être en désaccord avec @Lukas Eder et suggérer que c'est un tour terrible ; parce que l'intention de cette action s'approche de 0% d'évidence à partir du code. Si vous utilisez Java et que vous avez un String qui contient des chiffres et que vous voulez convertir ledit String à un int Je vous suggère d'utiliser Integer.parseInt(yourString); .

Cette technique a l'avantage d'être évidente pour le futur programmeur de maintenance.

3voto

OscarRyz Points 82553

'0' est aussi un personnage. Il s'avère que les caractères en Java ont une valeur unicode (UTF-16). Lorsque vous utilisez la fonction - avec des caractères Java effectue l'opération avec les valeurs entières.

Par exemple, int x = 'A' - '0';// x = 17

0 votes

Il ne se plaint pas du tout. Vous pouvez faire int y = s.charAt(1) Tout va bien, sans erreur de compilation ou d'exécution (en supposant que s a plus de deux caractères). Je pense que l'OP ne comprenait pas pourquoi il n'obtenait pas le même résultat.

0 votes

@Bart : UTF-16 est un format d'encodage pour l'unicode, mais oui vous avez raison.

1 votes

@Mark : Je sais, mais pour les caractères au-dessus du point unicode 65k, (au moins) deux caractères UTF-16 sont utilisés.

1voto

khachik Points 12589

char sont convertis en int implicitement :

   public static void main(String [] args) throws Exception {
     String bar = "abc";
     int foo = bar.charAt(1) - '0';
     int foob = bar.charAt(1);
     System.err.println("foo = " + foo + "   foob = " + foob);
   }

sortie : foo = 50 foob = 98 .

Peut-être que tu as mis deux int foo ... et c'est parce que ça n'a pas marché ?

1voto

ColinD Points 48573

Le code suivant fonctionne parfaitement bien !

int foo = bar.charAt(1);

Comme pour les types de référence, toute primitive Java peut être assignée sans casting à une autre primitive d'un type dont elle est considérée comme un sous-type. Les règles de sous-typage des primitives sont les suivantes JLS section 4.10.1 . char est considéré comme un sous-type de int donc tout char peuvent être affectés à un int .

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X