在没有双精度类型的C编译器上解析双精度IEEE浮点

baa*_*der 23 c c++ casting avr

我正在使用8位AVR芯片.64位double没有数据类型(double只映射到32位float).但是,我将通过Serial接收64位双精度数,并且需要在Serial上输出64位双精度数.

如何在不进行转换的情况下将64位双精度转换为32位浮点数并再次返回?32位和64位的格式都遵循IEEE 754.当然,我假设转换为32位浮点时精度会下降.

为了从64位转换为32位浮点数,我正在尝试这样做:

// Script originally from http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1281990303
float convert(uint8_t *in) {
  union {
    float real;
    uint8_t base[4];
  } u;
  uint16_t expd = ((in[7] & 127) << 4) + ((in[6] & 240) >> 4);
  uint16_t expf = expd ? (expd - 1024) + 128 : 0;
  u.base[3] = (in[7] & 128) + (expf >> 1);
  u.base[2] = ((expf & 1) << 7) + ((in[6] & 15) << 3) + ((in[5] & 0xe0) >> 5);
  u.base[1] = ((in[5] & 0x1f) << 3) + ((in[4] & 0xe0) >> 5);
  u.base[0] = ((in[4] & 0x1f) << 3) + ((in[3] & 0xe0) >> 5);
  return u.real;
}
Run Code Online (Sandbox Code Playgroud)

对于像1.0和2.0这样的数字,上面的工作,但是当我测试传入1.1作为64位双,输出有点(字面意思,不是双关语!),虽然这可能是一个问题我的测试.看到:

// Comparison of bits for a float in Java and the bits for a float in C after
// converted from a 64-bit double. Last bit is different.
// Java code can be found at https://gist.github.com/912636
JAVA FLOAT:        00111111 10001100 11001100 11001101
C CONVERTED FLOAT: 00111111 10001100 11001100 11001100
Run Code Online (Sandbox Code Playgroud)

Ton*_*nyK 5

IEEE指定了五种不同的舍入模式,但默认使用的是舍入舍入的一半.所以你有一个10001100 11001100 11001100 11001100形式的尾数...你必须将其四舍五入到24位.将位从0(最高有效)编号,位24为1; 但这还不足以告诉你是否要将第23位上升到第二位.如果所有剩余的比特都是0,则不会向上舍入,因为第23位为0(偶数).但是剩下的比特不是零,所以你在所有情况下都要整理.

一些例子:

10001100 11001100 11001100 10000000 ...(全零)不会向上舍入,因为第23位已经是偶数.

10001100 11001100 11001101 10000000 ...(全为零)向上舍入,因为第23位是奇数.

10001100 11001100 1100110x 10000000 ... 0001总是向上舍入,因为其余位不全为零.

10001100 11001100 1100110x 0xxxxxxx ...从不向上舍入,因为第24位为零.