数值编码之TwosComplement编码方式的计算

目录

内容与介绍

从TwosComplement编码转换成数值

从数值表示为TwosComplement编码

TwosComplement编码的计算

业务场景实现


内容与介绍

在汽车通讯领域,有一个普遍的业务场景,就是将从汽车电脑中接收到的数据按照一定的规则进行解析成现实物理中的数据。

对于接收到的数据有多种解码的方式,其中一种就是按TwosComplement方式解码,在进行具体解码之前,我们来了解下TwosComplement的概念。

TwosComplement可以翻译为二进制补码,TwosComplement是我们所知的计算机系统表示有符号整数的方式,在计算机系统中,正数在内存中的存储内容是其二级制表示,比如65,按1字节存储的话就是0b01000001(0b表示是二级制表示),这是它的原码,也是它的补码,所以正数的补码==原码;

对于负数-65,先将65的二级制0b01000001进行每位取反:

0b01000001

0b10111110

再对取反后的值+1:

0b10111110

0b10111111

最终在计算机中-65在内存中的存储内容是0b10111111

从TwosComplement编码转换成数值

我们以0xFFFFFFFF为例,当前是补码格式,用二级制表示:

0b1111 1111 1111 1111 1111 1111 1111 1111

最高位(最左边)的bit为1,表示是一个负数,在补码格式中,最高位bit为1表示是负数,为0表示为正数,就是我们的符号位

将它的所有位进行反转得到:

0b0000 0000 0000 0000 0000 0000 0000 0000

再加1

0b0000 0000 0000 0000 0000 0000 0000 0001

表示数值为1,又因为是负数,所以0xFFFFFFFF表示-1

从数值表示为TwosComplement编码

假如数值-30,我们想用TwosComplement表示,首先我们将30用二级制表示:

0b0000 0000 0000 0000 0000 0000 0001 1110

将它的所有位进行反转得到:

0b1111 1111 1111 1111 1111 1111 1110 0001

再加1:

0b1111 1111 1111 1111 1111 1111 1110 0010

将二级制转换为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编码方式计算:

0b \quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad11\quad

0b0000 0000 0000 0000 0000 0000 0100 0101\left(69)

0b0000 0000 0000 0000 0000 0000 0000 1100\left(12)

-------------------

0b0000 0000 0000 0000 0000 0000 0101 0001\left(81)

  • 例子2

假设我们要将数字69减去12,如果使用十进制,则结果为69-12=69+\left(-12 \right )=57,为了得到-12,我们先用12

0b0000 0000 0000 0000 0000 0000 0000 1100\left(12)

再每位反转:

0b1111 1111 1111 1111 1111 1111 1111 0011

再加1,得到-12的补码表示:

0b1111 1111 1111 1111 1111 1111 1111 0100\left( -12\right )

现在我们在按照计算机中的样子进行计算

0b0000 0000 0000 0000 0000 0000 0100 0101\left(69)

0b1111 1111 1111 1111 1111 1111 1111 0100\left( -12\right )

-------------------

0b0000 0000 0000 0000 0000 0000 0011 1001\left(57)

最高位再进1位,那一位超过32bit被过滤掉了

  • 例子3

我们从12减去69,12-69=12+\left(-69 \right )=-57,同样的,为了得到-69,我们先用69

0b0000 0000 0000 0000 0000 0000 0100 0101\left(69)

再每位反转:

0b111111111111111111111111 1011 1010

再加1,得到-57的补码表示

0b111111111111111111111111 1011 1011\left(-69\right )

现在我们在按照计算机中的样子进行计算

0b111111111111111111111111 1011 1011\left(-69\right )

0b0000 0000 0000 0000 0000 0000 0000 1100\left(12)

-------------------

0b111111111111111111111111 1100 0111\left(-57 \right )

业务场景实现

当我们从汽车电脑读到一个80 00的时候,它的编码方式="TwosComplement",最终显示类型是Float32,我们应该怎么处理?

首先需要将80 00转换成整形int,80 00转换成二级制显示

0b1000 0000 0000 0000

最高位为1,表示是一个负数,对它进行每位转换:

0b0111 1111 1111 1111 1111

再加1:

0b1000 0000 0000 0000

其表示-32768

在代码中我们需要将两个字节的TwosComplement编码数据转换成int,我们假设int是4个字节,在处理它们时我们有一个技巧:

按照上面的例子,我们获取到2个字节的数据

当最高位不是1时,表示是一个正数,我们在2个字节前面添加2个字节的00,构成4字节大小的int数据,比如7FFF,我们在前面加2个字节构造成00007FFF

当最高位是1时,表示是一个负数,我们在2个字节前面添加2个字节的FF,构成4字节大小的int数据,比如8000,我们在前面加2个字节构造成FFFF8000

具体代码细节下一章再讲

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值