Converting 8 bytes to double [duplicate]

大兔子大兔子 提交于 2019-12-20 06:48:26

问题


I am facing some problem with converting 8 bytes to a double. I have following byte array

    0x98 0xf9 0x38  0x4e 0x3a 0x9f 0x1c 0x43

And I am trying to do following

     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];

But it is not giving the correct answer. I am getting out is equal to 4835915172658346392 and actual value is 2014093029293670.

Note: *((double *) (buf)) works fine but I don't think it would be compiler and OS safe.

Edit:

long mult[8];

I start with mult[0]=1


回答1:


You say that 0x98 0xf9 0x38 0x4e 0x3a 0x9f 0x1c 0x43 is supposed to represent 2014093029293670.

This is true if the former is the little-endian representation of that integer in IEEE754 binary64 format. So your approach by using byte-by-byte multiplication (or equivalently, bit shifts) is not going to work, because those are arithmetic operations.

Instead you need to alias that representation as a double. To do this portably, on a little-endian machine on which double is IEEE754 binary64:

static_assert( sizeof(double) == 8 );

double out;
memcpy(&out, buf, sizeof out);

If you want this code to work on a machine with different endianness then you will need to rearrange buf before doing the memcpy. (This is assuming that the representation is always obtained in little-endian format, which you didn't state).




回答2:


Note that your code could be written more elegantly:

double out = 0;
for (int i = 1; i < 8; i++) {
   mult[i] = 256 * mult[i - 1];
   out += buf[i - 1] * mult[i - 1]; 
}

In this way you can see more clearly where is error!




回答3:


Try this:

   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

or

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;
}

or

In 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));

In C++11, you can also use std::begin(buf) and std::end(buf) as the boundaries (include the header ), and in both languages you can use sizeof(buf) / sizeof(buf[0]) (or simply sizeof(buf)) for the size, all provided buf is actually an array and not just a pointer.



来源:https://stackoverflow.com/questions/26114300/converting-8-bytes-to-double

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!