目录
内容与介绍
在汽车通讯领域,有一个普遍的业务场景,就是将从汽车电脑中接收到的数据按照一定的规则进行解析成现实物理中的数据。
对于接收到的数据有多种解码的方式,其中一种就是按TwosComplement方式解码,在进行具体解码之前,我们来了解下TwosComplement的概念。
TwosComplement可以翻译为二进制补码,TwosComplement是我们所知的计算机系统表示有符号整数的方式,在计算机系统中,正数在内存中的存储内容是其二级制表示,比如65,按1字节存储的话就是(
表示是二级制表示),这是它的原码,也是它的补码,所以正数的补码==原码;
对于负数-65,先将65的二级制进行每位取反:
再对取反后的值+1:
最终在计算机中-65在内存中的存储内容是
从TwosComplement编码转换成数值
我们以0xFFFFFFFF为例,当前是补码格式,用二级制表示:
最高位(最左边)的bit为1,表示是一个负数,在补码格式中,最高位bit为1表示是负数,为0表示为正数,就是我们的符号位
将它的所有位进行反转得到:
再加1
表示数值为1,又因为是负数,所以0xFFFFFFFF表示-1
从数值表示为TwosComplement编码
假如数值-30,我们想用TwosComplement表示,首先我们将30用二级制表示:
将它的所有位进行反转得到:
再加1:
将二级制转换为16进制,得到0xFFFFFFE2,假如我们写如下代码:
#include <stdio.h>
int main() {
int myInt;
myInt = 0xFFFFFFE2;
printf("%d\n",myInt);
return 0;
}
将得到输出为-30
TwosComplement编码的计算
TwosComplement编码的优势就是让在计算机上的加减法变得简单,可以让加减法的电路设计统计,不然加法和减法需要设计成不同的操作,下面我们就用TwosComplement进行加减法,但是实际上我们都是在进行加法
- 例子1
假设我们要将两个数字69和12相加。如果使用十进制,则总和为81。我们用TwosComplement编码方式计算:
- 例子2
假设我们要将数字69减去12,如果使用十进制,则结果为,为了得到
,我们先用
再每位反转:
再加1,得到-12的补码表示:
现在我们在按照计算机中的样子进行计算
最高位再进1位,那一位超过32bit被过滤掉了
- 例子3
我们从12减去69,,同样的,为了得到
,我们先用
再每位反转:
再加1,得到的补码表示:
现在我们在按照计算机中的样子进行计算
业务场景实现
当我们从汽车电脑读到一个80 00的时候,它的编码方式="TwosComplement",最终显示类型是Float32,我们应该怎么处理?
首先需要将80 00转换成整形int,80 00转换成二级制显示
最高位为1,表示是一个负数,对它进行每位转换:
再加1:
其表示-32768
在代码中我们需要将两个字节的TwosComplement编码数据转换成int,我们假设int是4个字节,在处理它们时我们有一个技巧:
按照上面的例子,我们获取到2个字节的数据
当最高位不是1时,表示是一个正数,我们在2个字节前面添加2个字节的00,构成4字节大小的int数据,比如7FFF,我们在前面加2个字节构造成00007FFF
当最高位是1时,表示是一个负数,我们在2个字节前面添加2个字节的FF,构成4字节大小的int数据,比如8000,我们在前面加2个字节构造成FFFF8000
具体代码细节下一章再讲