负数的存储方式

你知道负数在计数机中是如何存储和运算的吗?一些问题,看似简单,其背后却蕴含了深刻的道理。如果你还不了解,那我们快来一起看看吧。

汽车ECU设计

负数的存储方式:原文配图 2

一个菜鸟程序猿的成长之路。116篇原创内容

公众号所有编码系统的设计,都在追求连续性和唯一性。

原码,反码和补码的演化,就在不断提高整数编码的这两方面性能。

负数的编码

在计算机中有符号数有三种表示方法,即原码,反码和补码。

原码:原码表示法在数值前面增加了一位符号位(即最高位为符号位):正数该位为0,负数该位为1(0有两种表示:+0 和 -0),其余位表示数值的大小。比如以八位数为例,50 = 0b00110010,-50= 1b00110010。

负数的存储方式:原文配图 1

观察原码的二进制码表示的整数图,我们发现两个bug!

bug1:存在重复0,分别为00000000和10000000

bug2:存在两个间断点,分别为

011111111->10000000,即127突变为-0

11111111->000000000,即-127突变为+0

为什么这么关心间断点,因为这涉及到整个范围内的数值连续性,任何的间断点都会导致溢出问题。所以这个间断点,越少越好。反码:0以及正数的反码就是其本身,也就是说0的反码还是0,一个正数的反码还是这个正数自身。而负数则不同,负数的反码,除了第一位符号位不变(还是 1 ),其余各位取反,这样就得到了它的反码。同样以8位数为例,50 = 0b00110010, -50 =0b11001101。

负数的存储方式:原文配图 3

对比观察反码与原码的二进制码表示的整数图,我们发现这一次取反,使右半边的图形,做了一次翻转,于是bug2中的间断点被修复了,也就是说间断点从2个变成了1个。

bug1:依然存在重复0。bug2:两个间断点减少到1个,不能再优化了。

补码:对负数的原码取反,再加1,这样就得到了它的补码。同样以8位数为例,50 =0b00110010, -50 = 0b11001110。

负数的存储方式:原文配图 4

对比观察补码与反码的二进制码整数图,我们发现这一次求补,使右半边的图形,向下移动了1,于是bug1中的重复点消失了,然后最小负整数从-127变成了-128。虽然还有一个中断点,但这个已经是最好的结果了。

总结

通过以上介绍,我们知道了原码、反码和补码的一些知识,我们尝试着总结下为什么计算机中会最终选择补码来进行存储和计算数字。

a. 计算机的运算器为了实现简单,倾向于在运算过程中将减法转换成加法,统一使用加法运算器进行计算。想要把减法转化成加法运算,就需要在运算时带着符号一起运算,而反码和补码可以带符号位一起运算,也就方便了将减法转换为加法。

b. 采用补码,可以解决编码中有+0和-0两种表示0的方式。

c. 补码表示的数字范围要比原码和反码大。如8位2进制,使用原码或反码表示的范围为[-127, +127], 而使用补码表示的范围为[-128, 127]。

本文转自知乎用户 三郎

点击原文查看链接

完

历史精华文章集合:

【汽车ECU设计】汽车总线文章合集

【汽车ECU设计】Autosar文章合集

【汽车ECU设计】工作思考合集

【汽车ECU设计】第51~100期目录

【汽车ECU设计】第1~50期目录

编程 · 目录

上一篇·C语言中的 typedef 关键字

阅读原文

← 返回文章列表