我遇到了将8个字节转换为double的问题。我有以下字节数组
0x98 0xf9 0x38 0x4e 0x3a 0x9f 0x1c 0x43
我正在尝试做以下
for (int i = 1; i < 8; i++)
mult[i] = 256 * mult[i - 1];
double out= buf[7] * mult[7] + buf[6] * mult[6] + buf[5] * mult[5] + buf[4] * mult[4] + buf[3] * mult[3] + buf[2] * mult[2] + buf[1] * mult[1] + buf[0] * mult[0];
但它没有给出正确的答案。我退出等于4835915172658346392,实际值是2014093029293670.
注意:*((double *) (buf))
工作正常,但我不认为编译器和操作系统安全。
编辑:
long mult[8];
我从mult[0]=1
答案 0 :(得分:1)
你说0x98 0xf9 0x38 0x4e 0x3a 0x9f 0x1c 0x43
应该代表2014093029293670
。
如果前者是IEEE754 binary64格式的整数的 little-endian表示,则为真。因此,使用逐字节乘法(或等效的位移)的方法不起作用,因为它们是算术运算。
相反,您需要将别名表示为double
。为了便于这样做,在double
是IEEE754 binary64的小端机器上:
static_assert( sizeof(double) == 8 );
double out;
memcpy(&out, buf, sizeof out);
如果您希望此代码在具有不同字节顺序的计算机上运行,则需要在执行buf
之前重新排列memcpy
。 (这假设表示总是以小端格式获得,您没有说明。)
答案 1 :(得分:0)
请注意,您的代码可以更优雅地编写:
double out = 0;
for (int i = 1; i < 8; i++) {
mult[i] = 256 * mult[i - 1];
out += buf[i - 1] * mult[i - 1];
}
通过这种方式,您可以更清楚地看到错误的位置!
答案 2 :(得分:-3)
试试这个:
double a;
memcpy(&a, ptr, sizeof(double));
where ptr is the pointer to your byte array. If you want to avoid copying use a union, e.g.
union {
double d;
char bytes[sizeof(double)];
} u;
// Store your data in u.bytes
// Use floating point number from u.d
或
int main()
{
unsigned char id[] = {1,2,3,4,5,6,7,8};
long long res = 0;
for (int b = 0; b < 8; ++b)
res |= ((long long)id[b]) << (b * 8);
unsigned char *ares = (unsigned char*)&res;
for (int i = 0; i < 8; ++i)
printf("%02x ", ares[i]);
return 0;
}
或
在C ++中:
double x;
char buf[sizeof(double)]; // your data
#include <algorithm>
// ...
std::copy(buf, buf + sizeof(double), reinterpret_cast<char*>(&x));
In C:
#include <string.h>
/* ... */
memcpy(&x, buf, sizeof(double));
在C ++ 11中,您还可以使用std :: begin(buf)和std :: end(buf)作为边界(包括标题),在这两种语言中,您可以使用sizeof(buf)/ sizeof (buf [0])(或简称sizeof(buf))的大小,所有提供的buf实际上是一个数组,而不仅仅是一个指针。