chaîne double à hex et chaîne hex à double

Ce que j’essaie de faire est de convertir un double en chaîne hexagonale, puis de nouveau en double.

Le code suivant effectue la conversion chaîne double à hexadécimal.

char * double2HexSsortingng(double a) { char *buf = new char[17]; // double is 8-byte long, so we have 2*8 + terminating \0 char *d2c; d2c = (char *) &a; char *n = buf; int i; for(i = 0; i < 8; i++) { sprintf(n, "%02X", *d2c++); n += 2; } *(n) = '\0'; } 

Cela semble fonctionner, cependant, je ne suis pas sûr de savoir comment convertir la chaîne résultante en double. S’il vous plaît donnez votre avis 🙂

Je suis surpris de voir que personne n’a mis au point la solution standard, qui est le spécificateur de format %a dans la norme ISO C99.

 #include  #include  #include  std::ssortingng double2hexastr(double d) { char buffer[25] = { 0 }; ::snprintf(buffer, 25, "%A", d); // TODO Check for errors return buffer; } double hexastr2double(const std::ssortingng& s) { double d = 0.0; ::sscanf(s.c_str(), "%lA", &d); // TODO Check for errors return d; } int main() { std::cout << "0.1 in hexadecimal: " << double2hexastr(0.1) << std::endl; std::cout << "Reading back 0X1.999999999999AP-4, it is "; std::cout << hexastr2double("0X1.999999999999AP-4") << std::endl; } 
 char *doubleToRawSsortingng(double x) { // Assumes sizeof(long long) == 8. char *buffer = new char[32]; sprintf(buffer, "%llx", *(unsigned long long *)&x); // Evil! return buffer; } double rawSsortingngToDouble(const char *s) { // Assumes sizeof(long long) == 8. double ret; sscanf(s, "%llx", (unsigned long long *)&ret); // Evil! return ret; } 
 char *doubleToRawSsortingng(double x) { const size_t bytesInDouble = 8; union { double value; unsigned char bytes[bytesInDouble]; } u; u.value = x; char *buffer = new char[bytesInDouble * 2 + 1]; unsigned char *input = u.bytes; char *output = buffer; for(int i = 0; i < bytesInDouble; ++i) { sprintf(output, "%02hhX", *input); ++input; output += 2; } return buffer; } double rawStringToDouble(const char *input) { const size_t bytesInDouble = 8; union { double value; unsigned char bytes[bytesInDouble]; } u; unsigned char *output = u.bytes; for(int i = 0; i < bytesInDouble; ++i) { sscanf(input, "%02hhX", output); input += 2; ++output; } return u.value; } 

Ceci utilise le modificateur hh non standard. Si vous ne voulez pas l'utiliser, utilisez:

 unsigned int tmp = *input; sprintf(output, "%02X", tmp); unsigned int tmp; sscanf(input, "%02X", &tmp); *output = tmp; 

Pour MFC, convertissez double en CSsortingng 🙂

 CSsortingng MFCClass::DoubleToCSsortingng(double d, int beforKomma) { char a[17]="0123456789ABCDEF"; CSsortingng str = _T(""); double dInt=0,dPunkt=0; bool is_otr=0; if (d<0) {is_otr=1; d=-d;} dPunkt = modf(d, &dInt); //целая часть long ld = (long)dInt; long mask = 0xf; int it; while(ld>0) { it = ld&mask; ld = ld>>4; str.Insert(0,a[it]); }; // дробная часть //если целая часть 0: if (str.GetLength()==0) str += _T("0"); str += _T("."); for (int i=0; i 

-345.86783907228863 -> "-159.DE2" (beforKomma = 3)

Pour être honnête, utiliser sprintf est lent, mais vous pouvez l’inverser avec sscanf, en faisant presque exactement la même chose.

En fait, il vous faudrait copier chacun des deux caractères dans une chaîne tampon pour les décoder individuellement. Mon premier essai, ci-dessous est incorrect:

 double hexSsortingng2Double(char *buf) { char *buf2 = new char[3]; double a; char* c2d; c2d = (char *) &a; int i; buf2[2] = '\0' for(i = 0; i < 16; i++) { buf2[0] = *buf++; buf2[1] = *buf++; sscanf(buf2, "%X", c2d++); } return a; } 

Vous voyez,% X est décodé comme un entier, pas comme un octet. Cela peut même fonctionner, en fonction de problèmes bas / hauts / fin, mais c'est fondamentalement cassé. Alors, essayons de contourner cela:

 double hexSsortingng2Double(char *buf) { char *buf2 = new char[3]; double a; char* c2d; c2d = (char *) &a; int i; int decoder; buf2[2] = '\0' for(i = 0; i < 16; i++) { buf2[0] = *buf++; buf2[1] = *buf++; sscanf(buf2, "%X", &decoder); c2d++ = (char) decoder; } return a; } 

Sauf erreurs de syntaxe et autres, je pense que cela devrait fonctionner.

Presque la même procédure devrait faire

 void hex2double(const char* buf, double& a) { char tmpbuf[3]={0}; char *d2c; unsigned int tmp; d2c = (char *) &a; char *n = buf; int i; for(i = 0; i < 8; i++) { tmpbuf[0]=*buf++; tmpbuf[1]=*buf++; sscanf(tmpbuf, "%X", &tmp); *d2c++=tmp; } } 

Rapide et sale.

Notez cependant que cela joue avec le feu. Premièrement, vos chaînes hexagonales ne sont utilisables que sur des machines ayant le même format double et la même finalité. Deuxièmement, les fonctions de conversion ne respectent pas la règle de crénelage ssortingcte.

 #include  main() { union double_ull_t { double d; unsigned long long u; } x; scanf("%lf",&x.d); printf("%016llX %lf\n",xu,xd); scanf("%016llX",&x.u); printf("%016llX %lf\n",xu,xd); } 

Peut-être pas la solution la plus efficace, mais la plus facile à coder.

Vous voulez utiliser un syndicat et éviter cette mauvaise habitude:

char * d2c;

d2c = (car *) & a;

Pour simplement imprimer, ce n’est pas mauvais, c’est quand vous essayez de modifier d2c, puis vous utilisez un, c’est quand vous avez des problèmes. (Il en va de même pour deux variables ou pointeurs quelconques (ou tableaux) partageant la même mémoire (théorique).

 union { double f; unsigned long ul; } myun; myun.f = a; printf("0x%lX",myun.ul); to go the other way (scanf is also a very dangerous function that should be avoided). myun.ul=strtoul(ssortingng,NULL,16); a=myun.f; 

J’utilise la fonction ci-dessous, pour convertir double en hexadécimal.

 char * double2HexSsortingng(double a) { char *buf = new char[17]; // double is 8-byte long, so we have 2*8 + terminating \0 char *d2c; d2c = (char *) &a; char *n = buf; int i; for(i = 0; i < 8; i++) { sprintf(n, "%02X", *d2c++); n += 2; } *(n) = '\0'; } 

en passant 1,0 et 16,0 à cette fonction, les valeurs de retour observées sont respectivement 000000000000FF37 et 0000000000003040. Je pense que nous devrions obtenir 1 & 10.