2016-11-22 1 views
2

Dans mon application, j'essaie d'afficher la représentation en bits des variables doubles. Cela fonctionne pour les variables doubles plus petites. Ne fonctionne pas pour le niveau 10^30.Utiliser std :: bitset pour la représentation double

code:

#include <iostream> 
#include <bitset> 
#include <limits> 
#include <string.h> 

using namespace std; 

void Display(double doubleValue) 
{ 
    bitset<sizeof(double) * 8> b(doubleValue); 
    cout << "Value : " << doubleValue << endl; 
    cout << "BitSet : " << b.to_string() << endl; 
} 

int main() 
{ 
    Display(1000000000.0); 
    Display(2000000000.0); 
    Display(3000000000.0); 

    Display(1000000000000000000000000000000.0); 
    Display(2000000000000000000000000000000.0); 
    Display(3000000000000000000000000000000.0); 

    return 0; 
} 

Sortie:

/home/sujith% ./a.out 
Value : 1e+09 
BitSet : 0000000000000000000000000000000000111011100110101100101000000000 
Value : 2e+09 
BitSet : 0000000000000000000000000000000001110111001101011001010000000000 
Value : 3e+09 
BitSet : 0000000000000000000000000000000010110010110100000101111000000000 
Value : 1e+30 
BitSet : 0000000000000000000000000000000000000000000000000000000000000000 
Value : 2e+30 
BitSet : 0000000000000000000000000000000000000000000000000000000000000000 
Value : 3e+30 
BitSet : 0000000000000000000000000000000000000000000000000000000000000000 

Mon souci est pourquoi BITSET donne toujours 64, zéro pour plus tard 3. Fait intéressant "Cout" pour les valeurs réelles fonctionne comme prévu.

Répondre

4

Si vous regardez the std::bitset constructor vous verrez que ce soit prend une chaîne comme argument, ou un entier.

Cela signifie que votre valeur double sera convertie en un nombre entier, et il n'y a pas de type entier standard qui peut contenir ces grandes valeurs, et qui conduit à un comportement non défini .

Si vous voulez obtenir les bits réels du double que vous devez faire quelques tours de casting pour le faire fonctionner:

unsigned long long bits = *reinterpret_cast<unsigned long long*>(&doubleValue); 

Notez que type-punning comme celui-ci n'est pas définie dans la spécification C++, mais aussi longtemps comme sizeof(double) == sizeof(unsigned long long) cela fonctionnera. Si vous voulez que le comportement soit bien défini, vous devez passer par des tableaux de char et char*.

+1

Une alternative au type-punning dans ce cas pourrait être bon vieux 'std :: memcpy'. – Angew

+0

Vous devez utiliser C++ 14 pour obtenir un constructeur 'unsigned long long' pour' std :: bitset'. –

0

Avec 14 C++, std::bitset prend maintenant un constructeur unsigned long long, donc cela pourrait fonctionner:

union udouble { 
    double d; 
    unsigned long long u; 
}; 

void Display(double doubleValue) 
{ 
    udouble ud; 
    ud.d = doubleValue; 
    bitset<sizeof(double) * 8> b(ud.u); 
    cout << "Value : " << doubleValue << endl; 
    cout << "BitSet : " << b.to_string() << endl; 
} 

Cela devrait vous donner la représentation interne d'un double. Voir l'exemple de code de travail sur IdeOne.

+0

Malheureusement, les jeux de mots utilisant des unions ne sont pas définis en C++. Cela devrait fonctionner cependant. –