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 :

Longs stockés comme des doubles


Sujet :

Langage Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre Expert
    Inscrit en
    Août 2010
    Messages
    1 124
    Détails du profil
    Informations forums :
    Inscription : Août 2010
    Messages : 1 124
    Par défaut Longs stockés comme des doubles
    Bonjour,

    Je suis conscient qu'un double ne peut contenir un long quelconque de manière bijective, lorsque ce long est stocké dans la partie entière du double.

    Par contre, il me semble que Double.longBitsToDouble et Double.doubleToRawLongBits permettent une bijection (vu que les 2 types primitifs sont stockés sur le même nombre de bits).
    - Pourriez vous confirmer que cette méthode est effectivement une bijection (cf exemple ci dessous)
    - Ce qui me choque, c'est que l'opération est compatible avec la somme de double (voir les 3 dernieres lignes ci dessous). Est-ce que je peux compter sur ce comportement (ie ne pas avoir a repasser en long pour sommer) ? Avec vous une explication pour ce phénomène ?

    Merci d'avance pour vos lumières.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
     
           public static long lng2lng(long x) {
    		// long y = Double.doubleToLongBits(Double.longBitsToDouble(x));
    		long y = Double.doubleToRawLongBits(Double.longBitsToDouble(x));
    		if (x !=y) System.out.printf("%s != %s !",x ,y);
    		return y;
    	}
    	public static void main(String[] args) {
     
    		lng2lng(Long.MAX_VALUE);
    		lng2lng(Long.MIN_VALUE);
    		lng2lng(1246l);
    		lng2lng(0);
    		lng2lng(-1);
     
    		System.out.println(Double.longBitsToDouble(1)); 
    		System.out.println(Double.longBitsToDouble(1000)); 
    		System.out.println(Double.doubleToRawLongBits(Double.longBitsToDouble(1)+Double.longBitsToDouble(1000))); // wahou !
     
     
    	}

  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
    C'est quoi le but de la manoeuvre? Quel est pour toi l'intérêt d'aller déclarer un long comme un double?

    Sinon, pour répondre à tes questions: non ce n'est pas bijectif, il suffit de voir comment la méthode décrit son fonctionnement pour constater qu'il y a tout un range de bits qui sont transformés. Les NaN peuvent changer au niveau de la pattern sans prévenir.




    Et non l'addition ne marche pas comme ça. T'as juste du bol là parce que t'es resté dans le domaine restreint qui garde l'exposant et le signe de bits à 0.

    Donc pour résumé, non, non et c'est une idée à la con à oublier

  3. #3
    Membre Expert
    Inscrit en
    Août 2010
    Messages
    1 124
    Détails du profil
    Informations forums :
    Inscription : Août 2010
    Messages : 1 124
    Par défaut
    Hello Tchize_ et merci.

    Ok pour l'addition, ca m'étonnait aussi.

    Vu que les 2 types sont stockés sur le même nombre de bytes, il doit y avoir une bijection, ne serait-ce qu'à partir de la version serializée.
    J'ai quand même l'impression que cette transformation est bijective, de ce que j'ai pu en testé. Par contre elle semble dépendre de la JVM.

    En ce qui concerne le pourquoi, j'ai un problème de design que j'hésite à attaquer de manière propre. Je cherche à parraléliser des mappers sous Hadoop, cad:
    - j'ai un ensemble de "functions" : des classes héritant de Mapper<Ki,Vi,Ko,Vo>, pour plusieurs jeux de classes paramètriques <Ki,Vi,Ko,Vo>, qui définissent
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    map(Ki key, Vi value, Mapper<Ki,Vi,Ko,Vo>.Context ctx)
    Mon but est de créer un autre Mapper dont la méthode map() appele chaque Mapper.map() de mon ensemble, en lui passant un proxy du Context.
    Je ne sais trop comment gérer la multiplicité de types génériques possibles, vu que chaque map() que je dois appeler attends une classe générique concrète.
    Il est hors de question de paramétrer le mapper aggrégé par tous les types génériques des mappers wrappés (qui sont en nombre variables).

    En terme de performance, vu que les inputs/outputs de ces fonctions sont serialisées / deserialisées par hadoop, je me disais qu'interpréter un unique type primitif de multiples manières serait un bon compromis.

  4. #4
    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
    Citation Envoyé par shaiHulud Voir le message
    Hello Tchize_ et merci.

    Ok pour l'addition, ca m'étonnait aussi.

    Vu que les 2 types sont stockés sur le même nombre de bytes, il doit y avoir une bijection, ne serait-ce qu'à partir de la version serializée.
    J'ai quand même l'impression que cette transformation est bijective, de ce que j'ai pu en testé. Par contre elle semble dépendre de la JVM.
    Est-ce que tu as lu la javadoc? Elle dit tout le contraire.

    Consequently, for some long values, doubleToRawLongBits(longBitsToDouble(start)) may not equal start.
    En ce qui concerne le pourquoi, j'ai un problème de design que j'hésite à attaquer de manière propre.
    Ben fourrer des bits dans un double, c'est pas propre.



    Mon but est de créer un autre Mapper dont la méthode map() appele chaque Mapper.map() de mon ensemble, en lui passant un proxy du Context.
    Je ne sais trop comment gérer la multiplicité de types génériques possibles, vu que chaque map() que je dois appeler attends une classe générique concrète.
    Il est hors de question de paramétrer le mapper aggrégé par tous les types génériques des mappers wrappés (qui sont en nombre variables).
    Si tu montrait le code de ton wrapper qui englobe tout là. Il peut arrriver régulièrement qu'on ne puisse pas tout typer explicitement en java avec les génériques. Ca arrive quand tu as une chaine de dépendances entre tes types et que cette chaine est différente pour chaque élément de la map. Dans ce cas il aut passer par des <?> et un ignore warning.

  5. #5
    Membre Expert
    Inscrit en
    Août 2010
    Messages
    1 124
    Détails du profil
    Informations forums :
    Inscription : Août 2010
    Messages : 1 124
    Par défaut
    Pourtant,
    http://docs.oracle.com/javase/7/docs...ngBits(double)
    doubleToRawLongBits()
    ...
    In all cases, the result is a long integer that, when given to the longBitsToDouble(long) method, will produce a floating-point value the same as the argument to doubleToRawLongBits.

  6. #6
    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
    oui, ça c'est la relation double -> long -> double. On te dit que ça te donnera un double de la même valeur, pas que le champ de bits sera le même. Certains double on plusieurs réprésentations en bit, et c'est là ton problème.


    Toi tu parle de long -> double -> long et ça ce n'est pas garantis, au contraire.

Discussions similaires

  1. IBExpert : troncature des double precision ?
    Par Magnus dans le forum Outils
    Réponses: 1
    Dernier message: 25/08/2005, 15h07
  2. [TList]: trier des doubles
    Par PpPool dans le forum Langage
    Réponses: 6
    Dernier message: 11/08/2005, 11h34
  3. [JPEG] Traiter des Jpg comme des Bmp : Canvas
    Par Clorish dans le forum Langage
    Réponses: 9
    Dernier message: 20/07/2005, 11h14
  4. Procédure stockée : liste des serveurs SQL disponibles
    Par AF_STjohn dans le forum MS SQL Server
    Réponses: 3
    Dernier message: 15/06/2005, 20h11
  5. [C/C++] afficher des doubles dans une message box
    Par lalaurie40 dans le forum MFC
    Réponses: 1
    Dernier message: 24/05/2005, 14h55

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