6
votes

C / C ++ équivalent à DoubleTorwlongbits de Java ()

dans java double.doubletolongbits () est utile pour implémenter hashcode () méthodes.

J'essaie de faire la même chose en C ++ et d'écrire mon propre DoubleTorAwlongbits () méthode, comme après le chalutage de Google, je ne trouve pas de mise en œuvre appropriée.

Je peux obtenir le signifiant et l'exposant de std :: frexp (Numbr , & exp) et peut déterminer le signe mais ne peut pas comprendre l'utilisation des opérateurs bitwises pour obtenir l'équivalent Java.

Par exemple, Java's's Double.DoubletOtolLits () < / code> renvoie ce qui suit pour le double 3.94:

4616054510065937285

Merci pour toute aide.

Graham

ci-dessous est la documentation copié et collé de la double.doubletorawlongbits () xxx


1 commentaires

Le problème principal w / c est que la forme double binaire est indéfinie.


3 Réponses :


8
votes

Un simple casting fera: xxx pré>

où le bit de signe et les bits d'exposition dépend de votre plate-forme et de l'endansion. Si vos flotteurs sont IEE754, si le signe et l'exposant sont à l'avant et si char_bit == 8 code>, vous pouvez essayer ceci: p>

unsigned long long int u;
unsigned char * pu = reinterpret_cast<unsigned char *>(&u);
std::copy(buf, buf + sizeof(double), pu);


1 commentaires

Et pour générer une longue durée de conservation de Const * BUF?



4
votes
#include <stdint.h>

static inline uint64_t doubleToRawBits(double x) {
    uint64_t bits;
    memcpy(&bits, &x, sizeof bits);
    return bits;
}

5 commentaires

Cela suppose que la taille d'un double est de 64 bits, ce qui n'est pas nécessairement le cas.


@ROBK: Bien sûr. Mais sur les plates-formes où double ne correspond pas à IEEE -754 Double, la représentation des bits est peu probable d'être très utile pour un programme qui s'attend à ce que cela.


De la mention de la fonction HashCode () dans la question initiale, on dirait qu'il veut juste que la chaîne unique de bits représente le double à utiliser dans une fonction de hachage ou quelque chose comme ça.


Oui, par exemple, le hashcode () pour un objet Point3D peut être écrit en Java; qui en fait est facilement généré automatiquement à l'aide de NetBeans: Public int hachasde () {int hachage = 3; hachage = 59 * hachage + (int) (double.doubletolongits (this.mx) ^ (double.doubletolongbits (this.mx) >> 32)); hachage = 59 * hash + (int) (double.doubletolongits (this.my) ^ (double.doubletolongbits (this.my) >>> 32)); hachage = 59 * hash + (int) (double.doubletolongits (this.mz) ^ (double.doubletolongits (this.mz) >>> 32)); retour hachage; }


Les DoubleTorawbits () ci-dessus utilisant MEMCY () donnent exactement le même résultat que Java pour l'exemple de 3.94. C'est la solution la plus simple aussi.



2
votes

J'aime les syndicats pour ces types de choses. XXX

Je pense que cela le rend plus clair ce que vous faites et permet au compilateur faire tout le calcul.


6 commentaires

J'utilise souvent cette approche, mais sachez que de nombreux compilateurs actuels vont le casser à moins que l'analyse d'aliasing basée sur des types ne soit explicitement désactivée.


@Stephencanon Je sais que, dans la théorie, la lecture d'un membre d'un syndicat qui n'a pas été définie est un comportement indéfini, mais existe-t-il un compilateur qui pose des problèmes pour un idiome aussi connu et très utilisé?


@VOO: Il y en a eu plusieurs au fil des ans; Plus particulièrement une série de générations de GCC quelque part autour de 4.1.


Ceci est un comportement indéfini. Les autres solutions sur cette page sont correctes.


Microsoft utilise ce type de construction sur place dans leur API, par exemple dans USB_HUB_CAP_FLAGS. La norme nécessite que "la taille de l'union [T] [t] soit suffisante pour contenir le plus grand de ses membres de données non statiques. Chaque membre de données non statique est attribué comme s'il s'agissait de l'unique membre d'une structure. Tout Les éléments de données non statiques d'un objet union ont la même adresse "( Open-Std.org/jtc1/sc22/wg21/docs/papers/2013/n3690.pdf , sec. 9.5). Par conséquent, l'utilisation d'un syndicat de cette manière est effectivement nécessaire pour être équivalente à Reterpret_cast <> () sur l'adresse du VAR souhaité


Sérieusement, pourquoi d'autre utiliseriez-vous un syndicat? Quel bon serait-il?