C++ 双到十六进制字符串&;十六进制字符串到双精度

C++ 双到十六进制字符串&;十六进制字符串到双精度,c++,c,double,hex,C++,C,Double,Hex,我要做的是将一个double转换成十六进制字符串,然后再转换回double 下面的代码将双精度转换为十六进制字符串 char * double2HexString(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;

我要做的是将一个double转换成十六进制字符串,然后再转换回double

下面的代码将双精度转换为十六进制字符串

char * double2HexString(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';
}
char*double2hextstring(双a)
{
char*buf=new char[17];//double是8字节长的,因此我们有2*8+终止符\0
char*d2c;
d2c=(字符*)&a;
char*n=buf;
int i;
对于(i=0;i<8;i++)
{
sprintf(n,“%02X”,*d2c++);
n+=2;
} 
*(n) ='\0';
}
这似乎是可行的,但是,我不知道如何将结果字符串转换回double。
请注意:)

老实说,使用sprintf很慢,但您可以使用sscanf恢复它,做几乎完全相同的事情

实际上,你必须将每两个字符复制到一个缓冲字符串中,然后分别解码。我的第一次尝试,下面是不正确的:

double hexString2Double(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;
}
double-hexString2Double(char*buf)
{
char*buf2=新字符[3];
双a;
char*c2d;
c2d=(字符*)&a;
int i;
buf2[2]='\0'
对于(i=0;i<16;i++)
{
buf2[0]=*buf++;
buf2[1]=*buf++;
sscanf(buf2,“%X”,c2d++);
}
返回a;
}
您可以看到,%X被解码为int,而不是字节。它甚至可以工作,这取决于低端/高端问题,但它基本上是坏的。那么,让我们试着绕过这个问题:

double hexString2Double(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;
}
double-hexString2Double(char*buf)
{
char*buf2=新字符[3];
双a;
char*c2d;
c2d=(字符*)&a;
int i;
整数译码器;
buf2[2]='\0'
对于(i=0;i<16;i++)
{
buf2[0]=*buf++;
buf2[1]=*buf++;
sscanf(buf2、%X、&解码器);
c2d++=(字符)解码器;
}
返回a;
}

除非出现语法错误之类的问题,否则我认为这应该是可行的。

几乎相同的过程也应该如此

char *doubleToRawString(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;
}
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;
   }
}
void hex2double(const char*buf,double&a)
{
char tmpbuf[3]={0};
char*d2c;
无符号整数tmp;
d2c=(字符*)&a;
char*n=buf;
int i;
对于(i=0;i<8;i++)
{
tmpbuf[0]=*buf++;
tmpbuf[1]=*buf++;
sscanf(tmpbuf、%X、&tmp);
*d2c++=tmp;
}
}
又快又脏

然而,请注意,这是在玩火。首先,十六进制字符串只能在具有相同双精度格式和相同尾数的计算机上使用。其次,转换函数缺少严格的别名规则。

\include
char *doubleToRawString(double x) {
    // Assumes sizeof(long long) == 8.

    char *buffer = new char[32];
    sprintf(buffer, "%llx", *(unsigned long long *)&x);  // Evil!
    return buffer;
}

double rawStringToDouble(const char *s) {
    // Assumes sizeof(long long) == 8.

    double ret;
    sscanf(s, "%llx", (unsigned long long *)&ret);  // Evil!
    return ret;
}
main(){ 双联管{ 双d; 无符号长u; }x; 扫描频率(“%lf”和x.d); printf(“%016llX%lf\n”,x.u,x.d”); scanf(“%016llX”和x.u); printf(“%016llX%lf\n”,x.u,x.d”); }

也许不是最有效的解决方案,但最容易编码。

您希望使用联合并避免这种坏习惯:

char*d2c

d2c=(字符*)&a

因为只是打印它并不坏,当你试图修改d2c,然后使用a是当你遇到麻烦。(对于共享相同(理论)内存的任意两个变量或指针(或数组)也是如此


我正在使用下面的函数,将double转换为十六进制

char * double2HexString(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'; 
}  
char*double2hextstring(双a)
{ 
char*buf=new char[17];//double是8字节长的,因此我们有2*8+终止符\0
char*d2c;
d2c=(字符*)&a;
char*n=buf;
int i;
对于(i=0;i<8;i++)
{ 
sprintf(n,“%02X”,*d2c++);
n+=2;
}  
*(n) ='\0';
}  

将1.0和16.0传递给此函数,观察到的返回值分别为000000000000FF37和0000000000003040。我认为我们应该得到1和10。

对于MFC,将double转换为CString:)

CString MFCClass::DoubleToCString(双d,int-beforKomma)
{
字符a[17]=“0123456789ABCDEF”;
CString str=_T(“”);
双力=0,双力=0;
布尔值等于0;
如果(d0)
{
it=ld&mask;
ld=ld>>4;
str.Insert(0,a[it]);
};
// дробная часть
//если целая часть 0:
如果(str.GetLength()==0)str+=\u T(“0”);
str+=\u T(“.”);

对于(inti=0;i“-159.DE2”(beforKomma=3)

我惊讶地发现没有人提出标准解决方案,这就是ISO C99标准中的
%a
格式说明符

#include <iostream>
#include <string>
#include <stdio.h>

std::string double2hexastr(double d) {

  char buffer[25] = { 0 };

  ::snprintf(buffer, 25, "%A", d); // TODO Check for errors

  return buffer;
}

double hexastr2double(const std::string& 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;

}
#包括
#包括
#包括
std::string double2hexastr(双d){
字符缓冲区[25]={0};
::snprintf(缓冲区,25,“%A”,d);//TODO检查错误
返回缓冲区;
}
double hexastr2double(常量std::string&s){
双d=0.0;
::sscanf(s.c_str(),“%lA”,&d);//TODO检查错误
返回d;
}
int main(){

std::您是想打印原始字节还是数字的十六进制表示?另外,您是否关心字符串本身(而不是代码)的可移植性?您更喜欢可移植、易于编码/读取或快速的解决方案?我更喜欢易于编码和读取的解决方案。我需要这个解决方案来在程序之间传递一些参数。更具体地说,第一个程序生成另一个程序,并向它传递编码为十六进制字符串的两倍。Strager,您所说的“字符串本身的可移植性”是什么意思?若在两种不同的硬件平台上使用,可移植性可能会出现问题,因为您使用的是二进制数据形式。大端机/小端机、网络字节顺序等都应该考虑在内。看起来strager在这一特定方法上胜过我,而且更适用implementation@Jahid这个问题问的是
double
而不是
长双精度
。如果您希望为
长双精度
执行此操作,则需要
“%LA”
转换说明符。您可能希望现在对我的答案进行投票。
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(string,NULL,16);
a=myun.f;
char * double2HexString(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'; 
}  
CString MFCClass::DoubleToCString(double d, int beforKomma)
{
    char a[17]="0123456789ABCDEF";
    CString 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<beforKomma; i++)
    {
        dPunkt*=16;
        dPunkt = modf(dPunkt, &dInt);
        str += a[(int)dInt];
    }

    if (is_otr) str.Insert(0,_T("-"));
    return (str);
}
#include <iostream>
#include <string>
#include <stdio.h>

std::string double2hexastr(double d) {

  char buffer[25] = { 0 };

  ::snprintf(buffer, 25, "%A", d); // TODO Check for errors

  return buffer;
}

double hexastr2double(const std::string& 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;

}