2

I need to accurately convert a long representing bits to a double and my soluton shall be portable to different architectures (being able to be standard across compilers as g++ and clang++ woulf be great too).

I'm writing a fast approximation for computing the exp function as suggested in this question answers.

double fast_exp(double val)
{
    double result = 0;

    unsigned long temp = (unsigned long)(1512775 * val + 1072632447);
    /* to convert from long bits to double,
   but must check if they have the same size... */
    temp = temp << 32;
    memcpy(&result, &temp, sizeof(temp));

    return result;
}

and I'm using the suggestion found here to convert the long into a double. The issue I'm facing is that whereas I got the following results for int values in [-5, 5] under OS X with clang++ and libc++:

0.00675211846828461
0.0183005779981613
0.0504353642463684
0.132078289985657
0.37483024597168
0.971007823944092
2.7694206237793
7.30961990356445
20.3215942382812
54.8094177246094
147.902587890625

I always get 0 under Ubuntu with clang++ (3.4, same version) and libstd++. The compiler there even tells me (through a warning) that the shifting operation can be problematic since the long has size equal or less that the shifting parameter (indicating that longs and doubles have not the same size probably)

Am I doing something wrong and/or is there a better way to solve the problem being as more compatible as possible?

4

1 回答 1

6

首先,使用“long”是不可移植的。使用 stdint.h 中的固定长度整数类型。这将减少检查相同大小的需要,因为您将知道整数的大小。

您收到警告的原因是在 32 位整数上左移 32 位是未定义的行为。 将 32 位变量移位 32 位有什么不好?

另请参阅此答案:假设 sizeof(double) >= sizeof(void*) 是否安全? 假设双精度为 64位应该是安全的,然后您可以使用 uint64_t 来存储原始十六进制。无需检查尺寸,一切都是便携式的。

于 2013-11-07T18:28:24.403 回答