IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Java Discussion :

Java et les types signés, ça marche comment?


Sujet :

Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Décembre 2009
    Messages
    31
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Décembre 2009
    Messages : 31
    Par défaut Java et les types signés, ça marche comment?
    Bonsoir,

    Dans le cadre d'un projet, je dois réalisé une appli Java qui communique avec plusieurs matériels via JNI. Du coup, j'ai besoins de travailler en unsigned pour pas mal de chose. La plupart du temps, j'utilise le type "byte" (8bits signé). Mais j'ai un problème...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    byte test = -1;
    System.out.println(Integer.toBinaryString(test));
     
    //11111111111111111111111111111111
     
    test = 125;
    System.out.println(Integer.toBinaryString(test));
     
    //1111101
    Donc, si je me souvient bien de mes cours d'infos, mon byte Java est sur 8 bits. Il est signé, donc le dernier bit est utilisé pour le signe. Du coup, on se retrouve avec une valeur max de 2⁷-1 (127).

    Quelqu'un peut m'expliquer pourquoi la valeur de "-1" tient sur 32 bits??? J'avoue que je comprends pas car je m'attendrais à une valeur de "11111111" (sur 8 bits).

    Merci d'avance

  2. #2
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Par défaut
    Integer.toBinaryString convertit un int, pas un byte, ton byte de -1 est donc promo d'abord en integer, donc étendu à 32 bits.

    Utilise Integer.toBinaryString(byte & 0xFF) pour n'avoir que les 8 bits de base.

  3. #3
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 582
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 582
    Par défaut
    Citation Envoyé par gagou7 Voir le message
    Quelqu'un peut m'expliquer pourquoi la valeur de "-1" tient sur 32 bits??? J'avoue que je comprends pas car je m'attendrais à une valeur de "11111111" (sur 8 bits).
    Tout ce qui tient sur 8 bits tient aussi sur 32 bits, de même que 64 bits, 128 bits, et aussi 9 bits, 10 bits... .

    -1 est une valeur de byte parfaitement correcte, et donc tient en effet sur 8 bits. Seulement, Integer.toBinaryString() ne traite que des ints, et les ints occupent 32 bits.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  4. #4
    Membre averti
    Profil pro
    Inscrit en
    Décembre 2009
    Messages
    31
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Décembre 2009
    Messages : 31
    Par défaut
    Merci pour l'explication, j'avais zappé la conversion en integer...

    J'ai toutefois une autre question: J'essaie d'utiliser des unsigned integer, du coup, mon raisonnement est le suivant.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    //Je lis des données équivalent à un unsigned int (32 bits), dans l'exemple je l'ai codé en dur
     
    byte[] bytes = {(byte) 0xE0,(byte) 0x3A,(byte) 0xEC,0x02};
     
    // Mes bytes sont en big-endian, du coup, pour récupérer la valeur, je fais comme ça:
     
    int value = (((bytes[0] & 0xff) << 24) | ((bytes[1] & 0xff) << 16) |
    				  ((bytes[2] & 0xff) << 8) | (bytes[3] & 0xff));
     
    //Jusque là tout ce passe bien. Mais ma variable "value" étant un integer (32 bits) signé, si je tente d'afficher la valeur, j'obtiens un nombre négatif (normal vu que mon nombre est grand et que le MSB est à 1).
     
    System.out.println(value); // -533009406 (en binaire: 11100000001110101110110000000010)
    Mon idée est de convertir mon "value" dans un type plus grand ("long" de 64bits) et d'enlever les bits mis à 1 qui font de lui un nombre négatif.

    En gros, mon "value" vaut : 11100000001110101110110000000010
    Une fois passer en "long", il devrait valoir: 11111111111111111111111111111111 11100000001110101110110000000010
    Je devrais pouvoir extraire la valeur positive grâce à "&0xFFFFFFFF".

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    System.out.println(((long)value)&0xFFFFFFFF); //Renvoie toujours un nombre négatif...
    Pourquoi est-ce que j'ai toujours un nombre négatif? La fonction d'affichage (System.out.println()) supporte les long et ne fait pas de conversion implicite en integer pourtant... Je devrais obtenir 3761957890, non?

    Merci encore une fois pour votre aide

  5. #5
    Membre éprouvé
    Homme Profil pro
    Inscrit en
    Août 2011
    Messages
    342
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Août 2011
    Messages : 342
    Par défaut
    Citation Envoyé par gagou7 Voir le message
    Merci pour l'explication, j'avais zappé la conversion en integer...

    J'ai toutefois une autre question: J'essaie d'utiliser des unsigned integer, du coup, mon raisonnement est le suivant.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    //Je lis des données équivalent à un unsigned int (32 bits), dans l'exemple je l'ai codé en dur
     
    byte[] bytes = {(byte) 0xE0,(byte) 0x3A,(byte) 0xEC,0x02};
     
    // Mes bytes sont en big-endian, du coup, pour récupérer la valeur, je fais comme ça:
     
    int value = (((bytes[0] & 0xff) << 24) | ((bytes[1] & 0xff) << 16) |
    				  ((bytes[2] & 0xff) << 8) | (bytes[3] & 0xff));
     
    //Jusque là tout ce passe bien. Mais ma variable "value" étant un integer (32 bits) signé, si je tente d'afficher la valeur, j'obtiens un nombre négatif (normal vu que mon nombre est grand et que le MSB est à 1).
     
    System.out.println(value); // -533009406 (en binaire: 11100000001110101110110000000010)
    Mon idée est de convertir mon "value" dans un type plus grand ("long" de 64bits) et d'enlever les bits mis à 1 qui font de lui un nombre négatif.

    En gros, mon "value" vaut : 11100000001110101110110000000010
    Une fois passer en "long", il devrait valoir: 11111111111111111111111111111111 11100000001110101110110000000010
    Je devrais pouvoir extraire la valeur positive grâce à "&0xFFFFFFFF".

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    System.out.println(((long)value)&0xFFFFFFFF); //Renvoie toujours un nombre négatif...
    Pourquoi est-ce que j'ai toujours un nombre négatif? La fonction d'affichage (System.out.println()) supporte les long et ne fait pas de conversion implicite en integer pourtant... Je devrais obtenir 3761957890, non?

    Merci encore une fois pour votre aide
    En faisant un et logique comme celui là tu ne mets jamais à 0 le bit de signe.

    Edit : faut que je compte les F D'abord ><

    Edit2 : pourquoi tu n'affectes pas directement à un long ?

  6. #6
    Membre averti
    Profil pro
    Inscrit en
    Décembre 2009
    Messages
    31
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Décembre 2009
    Messages : 31
    Par défaut
    Citation Envoyé par GPPro Voir le message
    En faisant un et logique comme celui là tu ne mets jamais à 0 le bit de signe.

    Edit : faut que je compte les F D'abord ><

    Edit2 : pourquoi tu n'affectes pas directement à un long ?
    Si je l'assigne directement en "long", ça ne change rien...

    En faite j'ai trouvé C'est que Java quand il voit un 0xffffffff, il le cast en integer par défaut, même si on fait "var&(long)0xffffffff", le cast aura lieu et le 0xffffffff vaudra toujours "-1". La solution c'est de lui dire que notre nombre est par défaut un "long", ce qui nous donne 0xffffffffL. Du coup, ça marche nickel maintenant:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    byte[] bytes = {(byte) 0xE0,(byte) 0x3A,(byte) 0xEC,0x02};
     
    int value = (((bytes[0] & 0xff) << 24) | ((bytes[1] & 0xff) << 16) |
    				  ((bytes[2] & 0xff) << 8) | (bytes[3] & 0xff));
     
    System.out.println(value&0xffffffffL);
    Merci encore !

  7. #7
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 582
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 582
    Par défaut
    Citation Envoyé par gagou7 Voir le message
    En faite j'ai trouvé C'est que Java quand il voit un 0xffffffff, il le cast en integer par défaut, même si on fait "var&(long)0xffffffff", le cast aura lieu et le 0xffffffff vaudra toujours "-1". La solution c'est de lui dire que notre nombre est par défaut un "long", ce qui nous donne 0xffffffffL.
    La cause et la résolution sont bonnes. Mais l'explication est incorrecte : Java ne cast rien vers int.

    0xffffffff est un int, dès le départ. Un int qui vaut -1.
    Lorsque Java voit une expression qui mêle des ints et des longs, comme
    Avec value de type long, et 0xffffffff de type intrinsèque int, Java décide que l'expression est de type le plus large : long.
    Il commence donc par élargir les types ints vers le type long. Donc il élargit 0xffffffff vers le type long. Valeurs en tant que int : -1. Donc valeur en tant que long : -1. Donc après conversion en long, il n'y a toujours que des 1, et donc appliquer un & dessus n'a aucun effet.

    En utilisant 0xffffffffL, c'est un long dès le départ, et c'est lui qui fait en sorte que l'expression soit de type long. Il n'a pas besoin d'être converti, et va effectivement faire passer tous les 32 bits de poids fort à zéro.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [TSQL]Comment utiliser les type BINARY ?
    Par toto4650 dans le forum Sybase
    Réponses: 4
    Dernier message: 21/12/2006, 17h38
  2. Réponses: 2
    Dernier message: 08/07/2006, 18h44
  3. comment gerer les types Objet(java)
    Par karray_ali dans le forum SQL Procédural
    Réponses: 6
    Dernier message: 09/05/2006, 23h27
  4. [C++ > C# 2.0] Comment transformer les types ?
    Par nyarla01 dans le forum C++/CLI
    Réponses: 1
    Dernier message: 16/03/2006, 12h36
  5. [VB.NET] Comment implementer les "Type" de VB6 ?
    Par cach dans le forum VB.NET
    Réponses: 2
    Dernier message: 07/02/2006, 10h48

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo