likes
comments
collection
share

你是不是已经忘了,原码,反码和补码

作者站长头像
站长
· 阅读数 8

前言

前两天,有位前同事和我说他去面试,面试官第一个问题就是问了原码反码补码的的概念和负数的二进制转换原理。他说他工作之后,这些底层原理太久没复习。只能记个大概。回答的不是很清晰。

仔细想想,好像自己的也快忘了。

所以现在,复习一下。

当然,这篇文章也适合初入计算机的同学和跨专业学习的小伙伴。文中关于二进制的描述以一个字节(八位)为基准。

原码,源码,补码到底是什么?

首先,我们需要了解。数字有进制这么一个说法。我们日常生活中的1,2,3,4...也就是被我们称为阿拉伯数字的这些数字,叫十进制数字

但我们的计算机无法直接存储十进制数字。计算机中只能存储二进制数字。我们在计算机中所看见的一切都是通过二进制数字转化而来的。

所以,什么是二进制数字?

官方回答:二进制是计算技术中广泛采用的一种数制。二进制数字是用0和1两个数码来表示的数。它的基数为2,进位规则是“逢二进一”,借位规则是“借一当二”,由18世纪德国数理哲学大师莱布尼兹发现。当前的计算机系统使用的基本上是二进制系统。 20世纪被称作第三次科技革命的重要标志之一的计算机的发明与应用,其运算模式正是二进制,同时证明了莱布尼兹的原理是正确的。

翻译一下就是:二进制是只有0和1组成的数字。比如 :01011011 (二进制);

二进制和十进制有什么区别?

十进制拥有:0,1,2,3,4,5,6,7,8,9 这十个数字(因为有十个基本数所以他叫10进制)

二进制拥有: 0,1 这两个数字。(因为只有两个基本数,所以他叫二进制)

看,很直观,位数种类只有2种的叫做二进制。位数种类有十种的叫做十进制。

并且十进制无法被计算机直接存储,但是二进制可以被计算机存储。(或者说整个计算机数据都是由二进制组成的。)

二进制和是如何转换为十进制的?

计算机中有一种存储单位叫做位字节(byte),一个字节有8位。

最高位是符号位,其余位数分别表示1,2,4,8,16,32,64。

如图

你是不是已经忘了,原码,反码和补码

那么图中的0和1是什么意思呢?1表示该位置代表的数参与加法运算,0表示该位置代表的数不参与加法运算。

比如,上图中的 00111111。大家有发现,这串数字前面两为0后面都为一。 首先我们看第一个数字0。上文说过。首位表示符号位。0表示正数,1表示负数。

所以00111111表示是一个正的0111111。

再看0111111。记得上面的那张图吗,每一位对应的不同的数字。0表示参与运算,1表示不参与运算。

所以0111111 = 32+16+8+4+2+1 === 63;

00111111(二进制) === 63(十进制);

同样的方法。再来几个例子

  1. 10111111(二进制) === -63(十进制)
  2. 00000011(二进制) === 1+2 = 3(十进制)
  3. 10011001(二进制) === 16+8+1 = -25(十进制)(首位为1所以是负数)

什么是原码?

原码就是计算机中对数字的二进制定点表示方法,首位为符号位,其余位数表示数字大小。

记得上面二进制和十进制的转换吗。

127(十进制) === 01111111(二进制); 01111111就是127的原码;

3(十进制)=== 00000011(二进制); 00000011 就是3的原码;

-25(十进制) === 10011001(二进制); 10011001就是-25的原码;

原码的作用,就是以二进制的形式表达一个十进制的数字。

什么是反码?

对于正数来说,原码 === 反码。 比如说:127十进制) 原码:01111111 反码:(01111111)

对于负数来说:反码 === 原码除符号位不变外,其余位数取反。 比如说:-25(十进制) 原码:10011001 反码:(11100110)

什么是补码?

对于正数来说;补码 === 原码 === 反码 比如说:127(十进制) 原码:01111111 反码:(01111111) 补码:(01111111)

对于负数来说:补码 === 反码 + 1; 比如说:-25(十进制) 原码:10011001 反码:(11100110) 补码:(11100111)

二进制数要如何运算?

因为二进制只存在0和1,所以,当二进制进行运算的时候,大于1的数需要进1变0.这就像我们十进制中的大于10的数需要进1变0一样。

举个例 00000001 + 00000001 === 00000010。 某尾两个1相加大于1,所以向前进一。该位归0

画了个草图,大伙凑合着看看。 你是不是已经忘了,原码,反码和补码

知道了这个机制后我们来尝试下把十进制数转化为二进制计算。

7+25 === 32; 7(十进制) === 00000111(二进制的7); 25(十进制) === 00011001 (二进制的25); 00011001 (二进制的25) + 00000111(二进制的7) === 00100000(二进制);

我们将00100000(二进制)再重新为十进制:00100000 === 32 === 7+25 === 00011001 (二进制的25) + 00000111(二进制的7);

这个计算好像没问题。但如果参与运算的数字中有一个负数,那就麻烦了。

举个例子 -7+25 === 18; -7(十进制) === 10000111(二进制的-7); 25(十进制) === 00011001 (二进制的25); 00011001 (二进制的25) + 10000111(二进制的-7) === 10100000(二进制); 我们再把10100000转回十进制:10100000 ==== -32;

你是不是已经忘了,原码,反码和补码 -7+25的二进制算法转换回来居然是-32;这明显不对啊。

所以。这里就拓展出了另一个概念,二进制中,参与运算的不是原码;而是补码。 或许已经有小伙伴发现了。上面我们出错的运算是我们在使用原码运算并且包含负数的前提条件下。

而正是因为存在这个问题,才会有反码和补码的概念。在计算机中,参与运算的并非原码而是补码。

还是拿-7+25举个例子; -7+25 === 18; -7(十进制) 原码:10000111 补码:11111001 ; 25(十进制) 原码:00011001 补码:00011001; 00011001 (25的补码) + 11111000(-7的补码) === 00010010 ; 我们再把00010010转回十进制:10100000 ==== 18;

像这样使用补码去运算,可以在即使是负数的情况下也保证运算正确。

一个有意思的现象

原码的范围是 -127 - 127

反码的范围是 -127 - 127

但是补码的范围确是 -128 - 127

总结

  1. 计算机中无法存储十进制数据,只能存储二进制数据。
  2. 二进制有三种码型:原码,反码,补码。
  3. 参与运算的都是补码。
  4. 正数的反码 === 该数的补码 === 该数的原码
  5. 负数的反码 === 该数符号位不变,其余位数取反
  6. 负数的补码 === 该数的反码+1
  7. 10000000 === -128 !== -0
  8. 00000000 === 0
  9. 补码的范围可以表示的区间为-128 -127,但原码和反码均为-127 - 127
转载自:https://juejin.cn/post/7151364978300174344
评论
请登录