【问题标题】:converting byte array to double - c将字节数组转换为双精度 - c
【发布时间】:2010-11-21 01:01:48
【问题描述】:

我正在尝试从 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);

但是,出于好奇,我想知道是否可以使用 shift 运算符解决此问题...

【问题讨论】:

  • 你还没有说“输入[16]”试图代表什么。它是一个 128 位的整数值,还是别的什么?
  • 您是否以 128 位无符号整数的形式将数字存储在“输入”中?
  • @Roddy:从他的算法看来,这些字符是 15 阶多项式(以 256 为底)中的系数。 (@paolo_,对吗?)
  • 正如 Adrian P. 所说,输入 [16] 向量是我想表示为 128 位无符号整数的位序列

标签: c bytearray


【解决方案1】:

编辑:如果没有 __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;

记住字节序

【讨论】:

  • 一旦他尝试对循环的 i>= 9 部分执行 (
【解决方案2】:

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

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

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

【讨论】:

    【解决方案3】:

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

    byte,一个整数类型和double,一个浮点类型(即不是整数类型)不是按位兼容的(即你不能只是将一堆字节的值移位到浮点类型并期待相同的结果。)

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

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

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

    【讨论】:

      【解决方案4】:

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

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

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

      【讨论】:

      • 迄今为止最简单的解决方案!
      【解决方案5】:

      【讨论】:

      • 我相信输入不是ascii,而是缓冲区中的浮点值。
      • 仅当输入是数字的字符串格式时才相关,如果他将双精度数转储到内存然后将其作为字符数组加载,这将失败。
      【解决方案6】:

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

      【讨论】:

        【解决方案7】:

        根据右边的运算符优先级

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

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

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

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2013-03-10
          • 1970-01-01
          • 2014-11-02
          • 1970-01-01
          • 1970-01-01
          • 2012-03-07
          • 2015-10-24
          相关资源
          最近更新 更多