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 manipulation des Long


Sujet :

Langage Java

  1. #1
    Modérateur
    Avatar de nouknouk
    Homme Profil pro
    Inscrit en
    Décembre 2006
    Messages
    1 655
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France

    Informations forums :
    Inscription : Décembre 2006
    Messages : 1 655
    Par défaut problème de manipulation des Long
    Bonsoir à tous,

    voilà, j'ai un souci qui me semble trivial, mais mes petits neurones n'arrivent pas à trouver la solution.

    Voilà un exemple de code ou je prends un Long (64bits), je le scinde en deux Integer(32bits) et je réessaye de les rassembler ensuite pour retrouver le Long original:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
            long DEUX_PUISSANCE_32 = 4294967296L;
     
            long inLong = 4609628819153601335L;
            int big = (int)(inLong / DEUX_PUISSANCE_32);
            int little = (int)(inLong % DEUX_PUISSANCE_32);
     
            long outLong = ((long)big * DEUX_PUISSANCE_32) + ((long)little);
     
            System.out.println("Result of internal manipulation ("+inLong+" / "+outLong+") is "+(inLong == outLong));
    Mon problème est que le résultat n'est pas celui escompté : inLong et outLong sont différents:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Result of internal manipulation (4609628819153601335 / 4609628814858634039) is false
    J'ai certainement raté un truc que j'arrive pas à débusquer... Si vous avez une idée, merci beaucoup d'avance

  2. #2
    Membre Expert

    Homme Profil pro
    Consultant informatique
    Inscrit en
    Janvier 2004
    Messages
    2 301
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : Finance

    Informations forums :
    Inscription : Janvier 2004
    Messages : 2 301
    Par défaut
    Hello,

    ce traitement est déconseillé: en effet, tous les nombres en java sont signés, et donc il y aura forcément des cas qui poseront problèmes (lorsque la représentation binaire du long contient un "1" au 32ème ou 64ème bit)... Ces nombres là ne pourront pas être convertis en int de manière cohérente, puisqu'ils seront convertis en nombres négatifs (même si ce n'est visiblement pas le problème que tu rencontres).

    Il faut préférer utiliser les opérateurs de décalages binaires (qui doivent de plus être beaucoup plus rapides)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    long l = ...;
    long big = l >>> 32; 
    long little = ...

  3. #3
    Modérateur
    Avatar de nouknouk
    Homme Profil pro
    Inscrit en
    Décembre 2006
    Messages
    1 655
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France

    Informations forums :
    Inscription : Décembre 2006
    Messages : 1 655
    Par défaut
    Citation Envoyé par Pill_S Voir le message
    Il y aura forcément des cas qui poseront problèmes (lorsque la représentation binaire du long contient un "1" au 32ème ou 64ème bit)
    Tout d'abord, merci pour ta réponse. Tu as complètement raison: j'avais complètement zappé que les entiers étaient signés et donc qu'il fallait faire une petite 'contorsion' pour stocker le 32ème et le 64ème bit.

    Mais dans mon exemple précis, comme tu le suggère, le 32ème bit comme le 64ème sont tous les deux à zéro, et pourtant je n'obtient pas le bon résultat à la fin.

    C'est donc ça qui m'étonne le plus. Une ptite idée ? Les opérations '/' et '%' sont elles prévues pour fonctionner aussi avec des Long ?

    Merci d'avance

  4. #4
    Membre Expert

    Homme Profil pro
    Consultant informatique
    Inscrit en
    Janvier 2004
    Messages
    2 301
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : Finance

    Informations forums :
    Inscription : Janvier 2004
    Messages : 2 301
    Par défaut
    Citation Envoyé par nouknouk Voir le message
    Les opérations '/' et '%' sont elles prévues pour fonctionner aussi avec des Long ?
    Oui, ils sont prévus pour fonctionner avec tous types numériques (float et double compris)...

    A vrai dire, je ne comprend pas pourquoi cela réagit comme cela...

  5. #5
    Modérateur
    Avatar de nouknouk
    Homme Profil pro
    Inscrit en
    Décembre 2006
    Messages
    1 655
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France

    Informations forums :
    Inscription : Décembre 2006
    Messages : 1 655
    Par défaut
    A y est, j'ai finalement compris le pourquoi du comment :

    En fait, c'était une erreur de ma part : le 32ème bit de mon nombre 'test' n'est pas un '0', mais un '1'.

    Le nombre en binaire donne ça:

    0011 1111 1111 1000 1011 0000 1111 1100 / 1111 1000 0000 1101 1100 0011 0011 0111

    La valeur de 'little' (ie. les bits de poids faible) devenait alors négative et la reconstruction ne pouvait pas marcher.

    En prenant soin de retrancher |Integer.MIN_VALUE| avant de stocker les valeurs dans les int (et en ajoutant |Integer.MIN_VALUE| au moment de la reconstruction du Long), tout rentre dans l'ordre:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
            long DEUX_PUISSANCE_32 = 4294967296L;
     
            long inLong = 4609628819153601335L;
     
            // NOTE: Integer.MIN_VALUE est négatif, d'où les '+'
            int big = (int)(inLong / DEUX_PUISSANCE_32 + Integer.MIN_VALUE);
            int little = (int)(inLong % DEUX_PUISSANCE_32 + Integer.MIN_VALUE);
     
            long outLong = (((long)big - Integer.MIN_VALUE) * DEUX_PUISSANCE_32) + little - Integer.MIN_VALUE;
     
            System.out.println("inLong="+inLong+" / outLong="+outLong+" / result="+(inLong == outLong));
    ...donne comme sortie:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    inLong=4609628819153601335 / outLong=4609628819153601335 / result=true
    Merci encore Pill_S

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

Discussions similaires

  1. WCF probléme de manipulations des objets
    Par mcmaxis dans le forum Windows Communication Foundation
    Réponses: 4
    Dernier message: 06/10/2010, 09h23
  2. Réponses: 1
    Dernier message: 08/05/2008, 14h28
  3. Réponses: 3
    Dernier message: 15/04/2008, 11h34
  4. Manipulation des Long en Java
    Par menzlitsh dans le forum Langage
    Réponses: 2
    Dernier message: 06/07/2007, 09h31
  5. Réponses: 16
    Dernier message: 30/01/2007, 00h20

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