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

Langage Java Discussion :

Problème de conversion 2 bytes en Integer


Sujet :

Langage Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Homme Profil pro
    Ingénieur de projets
    Inscrit en
    Mai 2007
    Messages
    103
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Ingénieur de projets
    Secteur : Industrie

    Informations forums :
    Inscription : Mai 2007
    Messages : 103
    Par défaut Problème de conversion 2 bytes en Integer
    Bonjour à tous,

    Tout est dans le titre du topic, mais je tiens à vous donner quelques explications (en meme temps, c'est mieux pour avoir un avis :p)


    Bon voici le contexte de mon problème.

    Je lis un tableau depuis un automate et je le lis en byte. Pour une raison dont je me souviens pas, j'enregistre tous ces bytes dans un tableau de int (première incohérence dans ma réflexion).

    J'ai ensuite créé une méthode qui me permet de convertir mes 2 bytes (reçu en int) en un entier.

    Voici le code:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
     public static int convert2ByteStringToInteger(int Int1, int Int0) {
            String Byte1 = Integer.toHexString(Int1);
            if (Int1 == 0) {
                Byte1 += "0";
            }
            String Byte0 = Integer.toHexString(Int0);
            if (Int0 == 0) {
                Byte0 += "0";
            }
            return (int) Integer.decode("0x" + Byte1 + Byte0);
        }//enf of convert2ByteStringToInteger
    Bon je ne sais pas si cette méthode de conversion est la meilleure -surement pas car je n'aurai pas posté sinon.


    Nous arrivons au problème.

    Toutes mes conversions étaient bonnes sauf lorsque je recevais des valeurs négatives.

    Par exemple, dans mon process automate, si j'envoie -9999 cela signifie que j'ai un défaut dans mon équipement.
    Cependant, au lieu d'avoir -9999, j'obtiens la valeur 55537 qui il me semble est la valeur non signée.


    Donc j'aimerai avoir quelques avis.

    1- est ce que cette façon de convertir est bonne?
    2- Est ce que si je lis mon tableau en byte que j'enregistre dans un tableau de byte au lieu de int, le problème pourrait s'arranger (je ne l'ai pas encore testé car mon automate est parti sur site...)
    3- Est ce que j'ai plus de chance de réussir mes conversions en utilisant des masques?


    Cordialement,

    MustOne

  2. #2
    Membre éclairé
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    71
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Septembre 2008
    Messages : 71
    Par défaut
    Il y a point pas très limpide dans ton problème. Pourquoi est-ce que tu convertis 2 byte en int ? On ne saisi pas la spécification de ce que tu veux faire et en effet, ça peut conduire à des choses incohérentes si tu as des valeurs négatives.

    Il me semble comprendre que, dans la méthode que tu mentionnes, tu veux "concaténer" les deux byte représentés sous forme d'entiers qui sont passés en argument en mettant le premier dans le second octet du résultat et le second dans le premier octet, résultat que tu peux obtenir très simplement avec des décalages comme dans :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    private static int convert(final int i1, final int i2) {
    	return (i1 << 8) + i2;
    }
    Voir même, pour plus de sureté:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    private static int convert(final int i1, final int i2) {
    	return ((i1 << 8) & 0x0000FF00) + (i2 & 0x000000FF);
    }
    C'est plus performant qu'avec des manipulations de chaînes de caractères.

    Ta méthode ne donne pas le même résultat ce qui me fait douter par rapport à ce que tu souhaites faire. En effet, si tu appelles ta méthode avec les valeurs 28 et 3 par exemple (convert2ByteStringToInteger(28, 3)), on obtient, dans le corps de celle-ci :

    Byte1 = "1C"
    Byte0 = "3"
    "0x" + Byte1 + Byte0 = "0x1C3" => 451


    Alors qu'en toute logique, si on veut que Byte0 soit l'octet de poids faible du nombre résultant et Byte1 l'octet de poids le plus fort, il faudrait ajouter un zéro à la chaîne de caractère Byte0 (dans ce cas) :

    Byte1 = "1C"
    Byte0 = "03"
    "0x" + Byte1 + Byte0 = "0x1C03" => 7171


    Tout ça pour dire que, si ce que tu veux faire est :

    i1 = 0x000000XX
    i2 = 0x000000YY
    => i = 0x0000XXYY


    Il faut utiliser la méthode que je t'ai proposée. Sinon, je n'ai pas compris ton objectif. Par ailleurs, s'il y a des valeurs négatives, notamment Int0, le résultat n'a pas de sens.

    N'hésites pas à poster quelques précisions si tu veux plus d'infos !!
    Bon courage.

  3. #3
    Membre confirmé
    Homme Profil pro
    Ingénieur de projets
    Inscrit en
    Mai 2007
    Messages
    103
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Ingénieur de projets
    Secteur : Industrie

    Informations forums :
    Inscription : Mai 2007
    Messages : 103
    Par défaut
    Hello,

    Deja, merci pour ta réponse, et je n'hésite pas à donner de plus amples indications.... enfin je vais essayer.


    Il y a point pas très limpide dans ton problème. Pourquoi est-ce que tu convertis 2 byte en int ? On ne saisi pas la spécification de ce que tu veux faire et en effet, ça peut conduire à des choses incohérentes si tu as des valeurs négatives.
    En fait, si je vais cela, c'est que la première fois que j'ai voulu lire dans mon automate, j'avais créé la méthode sans penser au nombre négatif (on ne m'avait pas fait cette précision, c'était vraiment pour débuter JAVA et apprendre à faire une communication entre mon applet et mon automate).
    Ce qui est vraiment bête car lorsque je demande mes infos à mon automate, je lui demande une réponse byte/byte et comme un nul, je les range dans un tableau de int.


    Maintenant, je vais donner des précisions.


    Dans mon automate, j'ai ce qu'on appelle un DB - pour Data Block- dans lequel on stocke toutes les informations que l'on a besoin à l'utilisation d'une fonction.

    Qui dit "toutes les informations" dit tous types: byte, bit, integer, char, real...

    La première chose que je me suis dis est:"comment rapatrier les données car?", j'aurais pu lire chaque ligne en fonction du type, mais ca serait éternellement long.

    Donc j'ai opté pour une lecture byte/byte, qui est à mon avis plus simple à traiter.

    Et pour une raison dont je ne comprend pas j'ai enregistré le tout dans un tableau de int.

    Revenons aux type de données. Généralement, je lis des bits pour les états de mes entrées/sorties (côté automate) et des entiers pour les valeurs process (exemple, la température extérieure m'est retournée par la valeur 200 pour 20°C - un choix technique).


    Donc si je lis mon tableau (le DB) byte/byte, vous êtes bien d'accord que je vais trouver ma température en 2 bytes - le poids fort et le poids faible.

    D'où la necessité de reconvertir mes 2 bytes en int.

    Pourquoi il me faut les valeurs négatives? tout simplement parce qu'une température peut être négative (si on reste dans mon example)....rahh l'hiver lol

    Donc voila l'histoire :p


    Concernant ma méthode de conversion, je pense que je n'ai pas eu assez de recule pour voir mes erreurs.... mais bon. je savais de toute facon qu'elle n'était pas "propre".


    Ai-je bien étayé mon problème?

  4. #4
    Membre éclairé
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    71
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Septembre 2008
    Messages : 71
    Par défaut
    Bon, soyons clair, ton problème n'est pas forcément immédiat parce que les résultats dépendent beaucoup de la représentation utilisée pour les données, notamment de leur format binaire.

    On va prendre l'exemple de la valeur d'une température de -5°C. Imaginons que cette donnée est lue par un capteur thermique qui peut la fournir sous forme d'un nombre entier (sur 32 bits). La représentation binaire de la valeur décimale -5 peut être :

    10000000,00000000,00000000,00000101

    Ou alors, si le capteur utilise une représentation des nombres négatifs en complément à deux (comme le langage Java) :

    11111111,11111111,11111111,11111011

    Maintenant, tu veux faire l'acquisition de cette donnée à l'aide d'un soft en Java sous la forme de deux valeurs de type byte. C'est déjà un problème parce qu'à la base, la donnée fait 4 octets. Si la représentation utilisée est le complément à 2, ça n'est pas trop problématique dans le cas d'un donnée dont la valeur absolue est inférieur à 32767 parce que 11111111,11111011 est toujours la représentation de la valeur décimale -5 mais sur 16 bits au lieu de 32. Par contre dans la cas de la première représentation (qui n'est pas la plus probable ceci dit), on perd le bit de signe.

    Autant dire que pour des données flottantes, c'est encore plus problématique.

    Pour ce qui est des valeurs que tu donnes dans ton premier "post", en Java:

    -9999 => 11011000,11110001

    Cette valeur est aussi la représentation non signée de 55537.

    Cette valeur, décomposée sous la forme de deux octets, nous donne:

    poids faible = 11110001 => -15
    poids fort = 11011000 => -40

    Si tu veux recréer la valeur d'origine sans perdre le signe, les méthodes que je t'ai proposées ne sont pas encore les bonnes puisque on veut obtenir une valeur entière (sur 32 bits). Il faut utiliser :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    private static int convert(final int i1, final int i2) {
    	return (i1 << 8) + (i2 & 0x000000FF);
    }
    Bon, voilà quelques infos en vrac, mais tout ça pour dire qu'il faut que tu fasses attention aux manipulations que tu fais sur les données, notamment en terme de trans-typage, de découpage des données en byte, de manipulation des données signées / non signées. Tout ça dépend des spécifications des différents éléments qui constituent ton système, de ton automate notamment. Quelle représentation des nombres négatifs utilise-t-il ? Quelles sont le plages de valeurs possibles ?

    En espérant que ça t'aide...

  5. #5
    Membre confirmé
    Homme Profil pro
    Ingénieur de projets
    Inscrit en
    Mai 2007
    Messages
    103
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Ingénieur de projets
    Secteur : Industrie

    Informations forums :
    Inscription : Mai 2007
    Messages : 103
    Par défaut hummm
    Encore merci pour tes explications.


    Je viens de regarder la représentation binaire de mon integer côté automate.
    Pour la valeur -9999, on a une représentation sur 16bits qui est celle que tu as donné dans le poste précédent.

    Donc il faut réadapter ta méthode de conversion (celle que tu viens de me proposer).

    Faut-il simplement changer le masque?

    Bon, voilà quelques infos en vrac, mais tout ça pour dire qu'il faut que tu fasses attention aux manipulations que tu fais sur les données, notamment en terme de trans-typage, de découpage des données en byte, de manipulation des données signées / non signées. Tout ça dépend des spécifications des différents éléments qui constituent ton système, de ton automate notamment. Quelle représentation des nombres négatifs utilise-t-il ? Quelles sont le plages de valeurs possibles ?
    Il n'empêche que ce genre de manipulation semble être triviales, mais je ferai plus attention la prochaine fois. Promis

  6. #6
    Membre éclairé
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    71
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Septembre 2008
    Messages : 71
    Par défaut
    Normalement, tu ne devrais pas modifier le masque dans le code Java. En effet un int Java est de toutes façons sur 32 bits donc tu peux conserver l'opération (i1 << 8) + (i2 & 0x000000FF) pour reconstituer ta donnée.

    Après je ne sais pas comment tu communiques avec ton automate mais s'il attend une donnée sur 16 bits, il suffit de ne copier que les deux octets de poids faible dans le flux que tu envois.

    Dans les faits, si tu es sûr de toujours envoyer des données signées sur 16 bits, je te conseil plutôt d'utiliser des short.

    Enfin, dans le cas où tu as des valeurs de type int dans ton code Java mais dont tu es certains qu'elles contiennent toujours des données qui peuvent être représentées sur 16 bits, tu peux toujours, sans perte de données, faire l'opération suivante (un bête cast) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    int i = -9999;
    short s = (short)i;
    s vaudra bien -9999.

    Au demeurant, tu seras bien obligé de passer à un moment où un autre par des opérations sur des type int et de re-caster ensuite en short car les opérations de décalage (<<) travaillent sur (et retournent) des nombres entiers.

    La méthode de reconstitution de ta donnée d'origine peut donc s'écrire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    private static short convert(final int i1, final int i2) {
    	return (short)((i1 << 8) + (i2 & 0x000000FF));
    }
    Bon courage

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

Discussions similaires

  1. Problème de conversion byte en hexa
    Par Arnaud Malabeux dans le forum C#
    Réponses: 11
    Dernier message: 04/05/2010, 15h24
  2. Conversion de bytes little endian en integer negatif
    Par fjullien dans le forum VB 6 et antérieur
    Réponses: 6
    Dernier message: 06/10/2009, 15h32
  3. Problème de conversion 'Year to Integer'
    Par crackspider7676 dans le forum SQL
    Réponses: 3
    Dernier message: 15/01/2008, 07h32
  4. [Sunopsis] Problème de conversion float -> integer
    Par kergoussel dans le forum Alimentation
    Réponses: 3
    Dernier message: 05/12/2007, 14h47
  5. [C#] Problème de conversion de byte[]
    Par LE NEINDRE dans le forum C#
    Réponses: 1
    Dernier message: 14/12/2006, 10h33

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