8

我正在尝试从 16 个元素的字节数组中获取数值(双精度)值,如下所示:

unsigned char input[16];
double output;
...
double a  = input[0];
distance = a;
for (i=1;i<16;i++){
    a = input[i] << 8*i;
    output += a;
}

但它不起作用。似乎包含左移结果的临时变量只能存储 32 位,因为经过 4 次 8 位移位操作后它会溢出。

我知道我可以使用类似的东西

a = input[i] * pow(2,8*i);

但是,出于好奇,我想知道是否有任何使用移位运算符来解决这个问题的方法......

4

7 回答 7

4

这里的问题是,确实 32 位变量不能移动超过 4*8 次,即您的代码仅适用于 4 个字符。

你可以做的是找到第一个重要的字符,并使用霍纳定律: a n x n + a n-1 n-1 + ... = ((...( a n x + a n-1 ).x + a n-2 ) . x + ... ) + a 0如下:

char coefficients[16] = { 0, 0, ..., 14, 15 };
int exponent=15;
double result = 0.;

for(int exponent = 15; exp >= 0; --exp ) {
   result *= 256.; // instead of <<8.
   result += coefficients[ exponent ];
}
于 2009-08-19T18:13:39.503 回答
4

编辑:如果没有__int128.

a = input[i] << 8*i;

表达式input[i]被提升为int( 6.3.1.1 ) ,它在您的机器上是 32 位的。为了克服这个问题,左手操作数必须是 64 位,如

a = (1L * input[i]) << 8*i;

或者

a = (long long unsigned) input[i] << 8*i;

并记住字节顺序

于 2009-08-19T17:25:18.930 回答
2

为什么不简单地将数组转换为双指针?

unsigned char input[16];

double* pd = (double*)input;

for (int i=0; i<sizeof(input)/sizeof(double); ++i)
    cout << pd[i];

如果您需要修复字节序,请在转换为双精度数组之前使用 STL reverse() 反转 char 数组。

于 2009-08-20T04:32:23.363 回答
2

简而言之,不,您不能通过位移将bytes 序列直接转换为 a ,如代码示例所示。double

byte, 整数类型和double, 浮点类型(即不是整数类型)不是按位兼容的(即,您不能只将一堆字节的值移位到浮点类型并期望得到等效的结果。)

1)假设字节数组是一个引用整数值的内存缓冲区,您应该能够byte通过位移将您的数组转换为 128 位整数,然后将生成的整数转换为double. 不要忘记字节序问题可能会根据 CPU 架构发挥作用。

2)假设字节数组是一个包含128位长双精度值的内存缓冲区,并且假设没有字节序问题,您应该能够将字节数组中的值memcpy成长双精度值

union doubleOrByte {
    BYTE buffer[16];
    long double val;
} dOrb;
dOrb.val = 3.14159267;
long double newval = 0.0;

memcpy((void*)&newval, (void*)dOrb.buffer, sizeof(dOrb.buffer));
于 2009-08-19T17:25:19.710 回答
1

你试过 std::atof:

http://www.cplusplus.com/reference/clibrary/cstdlib/atof/

于 2009-08-19T17:18:42.593 回答
1

您是否正在尝试将数字的字符串表示形式转换为实数?在这种情况下,C 标准 atof 是您最好的朋友。

于 2009-08-19T17:19:49.940 回答
0

基于运算符优先级的右侧

a = input[i] << 8*i;

在转换为双精度之前进行评估,因此您将 input[i] 移动 8*i 位,将其结果存储在 32 位临时变量中,从而溢出。您可以尝试以下方法:

a = (long long unsigned int)input[i] << 8*i;

编辑:不确定您的系统上双精度的大小是多少,但在我的系统上它是 8 个字节,如果您也是这种情况,您的输入数组的后半部分将永远不会被看到,因为即使移位也会溢出双类型。

于 2009-08-19T17:17:05.920 回答