C++ 双倍到十六进制字符串和十六进制字符串加倍
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/497472/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
double to hex string & hex string to double
提问by Ali
What I'm trying to do is to convert a double to hex string and then back to double.
我想要做的是将双精度转换为十六进制字符串,然后再转换回双精度。
The following code does conversion double-to-hex string.
以下代码将双精度字符串转换为十六进制字符串。
char * double2HexString(double a)
{
char *buf = new char[17]; // double is 8-byte long, so we have 2*8 + terminating #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;
}
char *d2c;
d2c = (char *) &a;
char *n = buf;
int i;
for(i = 0; i < 8; i++)
{
sprintf(n, "%02X", *d2c++);
n += 2;
}
*(n) = '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;
}
';
}
This seems work, however, I'm not sure how to convert the resulting string back to double. Please advise :)
这似乎有效,但是,我不确定如何将结果字符串转换回双精度。请指教 :)
回答by Ali
I am surprised to see nobody has come up with the standard solution, which is the %a
format specifier in the ISO C99 Standard.
我很惊讶地看到没有人提出标准解决方案,即%a
ISO C99 标准中的格式说明符。
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;
}
回答by strager
unsigned int tmp = *input;
sprintf(output, "%02X", tmp);
unsigned int tmp;
sscanf(input, "%02X", &tmp);
*output = tmp;
回答by strager
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);
}
This uses the non-standard hh
modifier. If you don't want to use that, use:
这使用了非标准hh
修饰符。如果您不想使用它,请使用:
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;
}
}
回答by RusVIPer
For MFC, convert double to CString :)
对于 MFC,将 double 转换为 CString :)
double hexString2Double(char *buf)
{
char *buf2 = new char[3];
double a;
char* c2d;
c2d = (char *) &a;
int i;
buf2[2] = 'double hexString2Double(char *buf)
{
char *buf2 = new char[3];
double a;
char* c2d;
c2d = (char *) &a;
int i;
int decoder;
buf2[2] = '#include <stdio.h>
main() {
union double_ull_t {
double d;
unsigned long long u;
} x;
scanf("%lf",&x.d);
printf("%016llX %lf\n",x.u,x.d);
scanf("%016llX",&x.u);
printf("%016llX %lf\n",x.u,x.d);
}
'
for(i = 0; i < 16; i++)
{
buf2[0] = *buf++;
buf2[1] = *buf++;
sscanf(buf2, "%X", &decoder);
c2d++ = (char) decoder;
}
return a;
}
'
for(i = 0; i < 16; i++)
{
buf2[0] = *buf++;
buf2[1] = *buf++;
sscanf(buf2, "%X", c2d++);
}
return a;
}
-345.86783907228863 -> "-159.DE2" (beforKomma=3)
-345.86783907228863 -> “-159.DE2”(Komma=3 之前)
回答by jpalecek
Almost the same procedure should do
几乎相同的程序应该做
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;
Quick & dirty.
又快又脏。
Note, however, that this is playing with fire. First, your hex strings are only usable on machines with the same double format, and the same endianness. Second, the conversion functions are short on strict aliasing rule.
但是请注意,这是在玩火。首先,您的十六进制字符串只能在具有相同双格式和相同字节序的机器上使用。其次,转换函数缺乏严格的别名规则。
回答by Daniel C. Sobral
Using sprintf is slow, to be honest, but you can revert it with sscanf, doing almost exactly the same thing.
老实说,使用 sprintf 很慢,但是您可以使用 sscanf 恢复它,做几乎完全相同的事情。
Well, actually, you'd have to copy each two characters to a buffer string, to decode each individually. My first try, below is incorrect:
嗯,实际上,您必须将每两个字符复制到一个缓冲区字符串中,以单独解码每个字符。我的第一次尝试,下面是不正确的:
char * double2HexString(double a)
{
char *buf = new char[17]; // double is 8-byte long, so we have 2*8 + terminating ##代码##
char *d2c;
d2c = (char *) &a;
char *n = buf;
int i;
for(i = 0; i < 8; i++)
{
sprintf(n, "%02X", *d2c++);
n += 2;
}
*(n) = '##代码##';
}
You see, %X is decoded as an int, not as a byte. It might even work, depending on low-ending/high-endian issues, but it's basically broken. So, let's try to get around that:
你看,%X 被解码为一个整数,而不是一个字节。它甚至可能工作,取决于低端/高端问题,但它基本上已经坏了。所以,让我们尝试解决这个问题:
##代码##Barring syntax errors and such, I think this should work.
除非语法错误等,我认为这应该有效。
回答by Sparr
Maybe not the most efficient solution, but the easiest to code.
也许不是最有效的解决方案,但最容易编码。
回答by old_timer
You want to use a union and avoid this bad habit:
您想使用联合并避免这种坏习惯:
char *d2c;
字符 *d2c;
d2c = (char *) &a;
d2c = (char *) &a;
For just printing its not bad, its when you try to modify d2c and then use a is when you get into trouble. (same is true for any two variables or pointers (or arrays) sharing the same (theoretical) memory.
只是打印还不错,当您尝试修改 d2c 然后使用 a is 时遇到麻烦。(对于共享相同(理论)内存的任何两个变量或指针(或数组)也是如此。
##代码##回答by Sai Krishna V
I am using the below function, to convert double to hexadecimal.
我正在使用以下函数将双精度转换为十六进制。
##代码##passing 1.0 & 16.0 to this function, the return values observed are 000000000000FF37 & 0000000000003040 respectively. I think we should get 1 & 10.
将 1.0 和 16.0 传递给该函数,观察到的返回值分别为 000000000000FF37 和 0000000000003040。我认为我们应该得到 1 和 10。