我正在分析处理指向点的前驱代码(代码在微控制器上运行),但我不了解事情是如何运作的。我必须知道如何将平面转换为十进制,反之亦然。但是,他所做的是在数据结构中使用自定义位字段表示exponent:6 bits
和mantissa:26 bit
。
typedef union {
struct {
#ifdef _BIG_ENDIAN
unsigned int mant: 26; /* -33,554,432 to +33,554,431 */
unsigned int exp: 6; /* 10^-32 to 10^+31 */
#else
unsigned int exp: 6; /* 10^-32 to 10^+31 */
unsigned int mant: 26; /* -33,554,432 to +33,554,431 */
#endif
} part;
unsigned long comp;
} DMKS;
随后是客户端的程序逻辑:
客户端(微控制器)从服务器获取数据并将值设置为unsigned long comp
致电M_to_u()
,将DMKS
值转换为micro value
M_to_u()
如下所示:
long M_to_u(DMKS dmks_val)
{
register unsigned int exp;
long retval;
UARTprintf("before x= %x\n", (dmks_val.comp));//First print of comp
retval = (long) (dmks_val.part.mant);
UARTprintf("retval x= %x\n", (long) (dmks_val.part.mant));//second print of mantissa
if (retval & 0xfe000000)
{
retval |= 0xfe000000;
}
exp = dmks_val.part.exp;
UARTprintf("exp = %d\n", (long) (dmks_val.part.exp));//Third print of exponent
//UARTprintf("exp x= %x\n", (long) (dmks_val.part.exp));
switch(exp) {
case 58:
retval /= 1000000L;
break;
case 59:
retval /= 100000L;
break;
case 60:
retval /= 10000L;
break;
case 61:
retval /= 1000L;
break;
case 62:
retval /= 100L;
break;
case 63:
retval /= 10L;
break;
case 0:
break;
case 1:
retval *= 10L;
break;
case 2:
retval *= 100L;
break;
case 3:
retval *= 1000L;
break;
case 4:
retval *= 10000L;
break;
default:
break;
}
return(retval);
}
打印出值
- IEEE 754 standard specifies a binary32 format example
- customized floating point in this codes = 11110100001001000000111101
mantissa exponent
+---+---+---+---+---+---+---+----+
| 11110100001001000000 | 111101 |
+---+---+---+---+---+---+---+----+
第一个UARTPrint :: before x= 3d0903d
,它是从服务器发送的联合中comp
的纯值, bin格式 = 11110100001001000000111101
尾数字段的第二次打印:: retval x= f4240
从尾数的位字段中提取, bin格式 = 11110100001001000000
第三次打印:: exp = 61
从指数的位字段中提取, bin格式 = 111101
问题是:
与 IEEE 754标准指定binary32 (exp bits:23~30, and mantissa bits:0 ~22)
不同,自定义位字段用于此代码中的浮点。
1。事情如何运作? - 此代码使用exp位:0~5和尾数位:6~30,因此客户/服务器需要操作 比特顺序?
2。为什么它除以1000L?
- 打印出来显示exp值= 61,所以进入case 61:
,但指数61
如何连接到divided by 1000L
?
由于 -Jin
答案 0 :(得分:0)
您的前任可能的工作方式,但这是一种不可靠且危险的方法 - struct
内的位域序列化顺序是实现定义的,并且不需要它与CPU用于整数的字节顺序一致(顺便说一句,不一定与用于硬件浮点的字节序相同!),声明的顺序,或其他任何。< / p>
由于您以这种自定义格式从微控制器接收unsigned long
,我会记下字段的顺序 - 看起来尾数是高位而指数是低位,每个字段内的位顺序与CPU的位顺序一致; 没有文档或测试可以依赖 - 然后使用显式位掩码来提取字段,例如
unsigned long mantissa = (dmks_val & 0xFFFFFFC0) >> 6;
unsigned long exponent = (dmks_val & 0x0000003F) >> 0;
其中dmks_val
现在是unsigned long
而不是联合。应该用火和剑从你的代码库中清除联盟。
我无法帮助您解决问题2.只有了解这种古怪浮点格式的人才能帮助您解决问题2.顺便说一下,您最好找到符号位。