【问题标题】:IEEE 754 arithmitic on 4 bytes(32 bits)4字节(32位)的IEEE 754算术
【发布时间】:2012-01-31 14:51:08
【问题描述】:

我编写此代码是为了对 4 字节字符串执行 IEEE 754 浮点运算。

它接收字节,将它们转换为二进制,然后用二进制得到符号、指数和尾数,然后进行计算。

这一切都几乎完美,0xDEADBEEF 给我 6259853398707798016,真正的答案是 6.259853398707798016E18,现在这些是相同的值,在我正在处理的项目中我不会有这么大的东西,所有其他较小的值都放在小数点在正确的地方。

这是我的代码: 浮动 calcByteValue(uint8_t 数据[]) { 诠释我; 整数 j = 0; 整数索引; 整数符号,exp; 浮法;

   char bits[8] = {0};
   int *binary = malloc(32*sizeof *binary);
   for (index = 0;index < 4;index++) {
      for (i = 0;i < 8;i++,j++) {
         bits[i] = (data[index] >> 7-i) & 0x01;
         if (bits[i] == 1) {
            binary[j] = 1;
         } else {
            binary[j] = 0;
         }
      }
      printf("\nindex(%d)\n", index);
   }

   sign = getSign(&(binary[0]));
   mant = getMant(&(binary[0]));
   exp = getExp(&(binary[0]));

   printf("\nBinary: ");
   for (i = 0;i < 32;i++)
      printf("%d", binary[i]);
   printf("\nsign:%d, exp:%d, mant:%f\n",sign, exp, mant);

   float f = pow(-1.0, sign) * mant * pow(2,exp);
   printf("\n%f\n", f);
   return f;
}

//-------------------------------------------------------------------

int getSign(int *bin) {
   return bin[0];
}

int getExp (int *bin) {
     int expInt, i, b, sum;
     int exp = 0;

     for (i = 0;i < 8;i++) {
        b = 1;
        b = b<<(7-i);
        if (bin[i+1] == 1)
           exp += bin[i+1] * b;
     }

     return exp-127;

}

float getMant(int *bin) {
   int i,j;
   float b;
   float m;
   int manBin[24] = {0};
   manBin[0] = 1;
   for (i = 1,j=9;j < 32;i++,j++) {
       manBin[i] = bin[j];
       printf("%d",manBin[i]);
   }
   for (i = 0;i < 24;i++) {
      m += manBin[i] * pow(2,-i);;
   }
   return m;
}

现在,我的老师告诉我,有一种更简单的方法,我可以只接收字节流,然后将其转换为浮点数,它应该可以工作。我试过那样做,但不知道我的生活是否依赖它。

我不是要你为我做作业,我已经完成并且正在工作,但我只需要知道我是否可以以不同的方式/更轻松/更有效地完成它。

编辑:我需要处理一些特殊情况,但这只是指数是否全为零等等等等。易于实施。

【问题讨论】:

  • “字符串”可能只是 32 位浮点数的 4 个字节,在这种情况下,您只需将这 4 个字节转换为浮点数,例如f = (float)str.
  • @MarcB,我认为值得指出的是,如果str 是一个字符串(即指向它的指针),它就不起作用。

标签: c coding-style floating-point byte ieee-754


【解决方案1】:

老师大概是这样想的:

char * str; // your deadbeef
float x;
memcpy(&x, str, sizeof(float));

对于字节序的问题,我建议不要这样做。但是如果你的老师想要它,他就会得到它。

【讨论】:

    【解决方案2】:

    我认为您想要一个联合 - 只需创建一个联合,其中一个成员是 4 个字符的数组,另一个是浮点数。写第一个,然后读第二个。

    【讨论】:

      【解决方案3】:

      看看你的代码做了什么,“4 字节字符串”看起来已经包含 32 位浮点数的二进制表示,因此它已经存在于内存中 data 指定的地址处,以大端字节顺序排列。

      您可以将数组data 转换为浮点指针并取消引用它(如果您可以假设您正在运行的系统是大端并且该数据将针对您平台上的浮点类型正确对齐)。

      或者,如果您需要更多控制(例如更改字节顺序或确保对齐),您可以使用 uint8_t 数组和浮点数的联合来研究类型双关语。将字节复制到 union 的 uint8_t 数组中,然后读取 float 成员。

      【讨论】:

      • 我只是一个可怜的小端。不过我会尝试做工会的事情。
      • @JamesCameron:在这种情况下(假设您像我提到的那样创建联合),您需要做的就是将字节从 data 以相反的顺序复制到联合中的 uint8_t 数组并返回浮动成员。
      【解决方案4】:

      这是我的工作代码:

          unsigned char val[4] = {0, 0, 0xc8, 0x41};
          cout << val << endl;
      
          cout << "--------------------------------------------" << endl;
          float f = *(float*)&val;
      
          cout << f << endl;
          return 0;
      

      【讨论】:

      • 不敢相信我是这么辛苦的。德普。我总是想太多。
      • 这是小端 BTW。实际字节值 = 0x41c80000
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-16
      • 2021-03-30
      • 1970-01-01
      • 2012-01-20
      • 2021-12-14
      相关资源
      最近更新 更多