二进制数的原码 反码 补码的由来,作用 及其如何互相转换:

由来

原码:
所谓原码就是机器数,是加了一位符号位的二进制数(因为数值有正负之分),正数符号位为0,负数符号位为1.
计算机中存储、处理、运算的数据通常是8位、16位、32位或64位的,这里以最简单的8位为例讲解。
注意符号位是包含在8位中的其中1位,故可直观读出的数只有7位(只有后7位数可以按权展开)。
求原码的方法:
正数:
将一个十进制正整数转换二进制数(带符号位), 即是这个数的原码.
负数:
先计算该负数绝对值的二进制。之后对其每个数"取反,然后加一。
比如-32
第一步:32(10)= 00100000(2)
第二步:求反:11011111
第三步:加1:11100000


反码:

由来: 用带符号位的原码进行乘除运算时结果正确,而在加减运算的时候就出现了问题,如: 用十进制表示:1 + (-1) = 0,
但用二进制表示:00000001 + 10000001 = 10000010, 将结果换算成十进制数也就是-2.
于是就发现问题出现在带符号位的负数身上为了解决二进制中正负数的加减问题,人们就在原码的基础上发明了反码,
反码的表示方式是用来处理负数的,符号位置不变,其余位置相反.
反码的取值空间和原码相同且一一对应.
所以1 + (-1) = 0, 用二进制就可以表示为:00000001 + 11111110 = 11111111, 在反码的表示形式中,11111111表示-0,所以就可以解决"二进制正负数相加等于0"的问题
求反码的方法是:原码取反后就是反码,正数不变,负数保留符号位1不变,剩下位按位取反. (1变0,0变1)

补码:

由来:虽然反码的出现解决了正负数的加减问题, 但却让0这个数字有了两种"形态": "0"和"-0", 但这是不合逻辑的,只应该有一个0,所以人们就又发明了补码.
在反码的基础上补一位就得到了补码, 但有失必有得, 需要丢掉最高位. 如反码中的"-0"表示为11111111, 补上一个1后为100000000, 将最高位的1去掉,就剩下
00000000.跟正数的0完美融合, 这样就解决了"0"和"-0"的问题.(人类的智慧是伟大的...)
下面再通过"正负数相加等于零"的问题来验证一下补码是否可用:
3 + (-3) = 0, 二进制表示: 00000011 + 11111101("-3"的补码) = 100000000, 去掉最高位并将结果换算成十进制: 0, 问题彻底解决.
求补码的方法:在反码的基础上补一个1.

转换方法:

分正数和负数
正数:
正数的原码与反码,补码都相同.

负数:
原码转反码: 符号位不变,其余位取反.  如: -6的原码为:10000110, 反码为11111001.
反码转补码: 直接补1即可. 如: -5的反码为:11111010, 补码为11111011.
原码转补码: 符号位不变,其余各位取反后补1, 也就是反码补1.
补码转原码: 退1后,除符号位各位取反.或先计算该负数绝对值的二进制。之后对其每个数“取反”,然后加一。

思考:java中为什么byte的取值范围是-128~127.

解释: java中byte占一个字节, 也就是8bit(位), 其中最高位是符号位, 剩下7位用来表示数值.若符号位为0, 则表示为正数,范围为00000000~01111111(补码形式),
也就是十进制的0-127. 若符号位为1, 则表示为负数, 范围为10000000~11111111(补码形式), -128~-1, 11111111转换为原码就是10000001,也就是-1.
在补码中,为了避免存在"-0",规定10000000为-128, 所以解释了byte的取值范围为什么是-128~127.

总结:
1. 计算机中的整数都是以补码的形式储存的,为的就是使计算机对整数的减加乘除操作不会出错.
2. 为了消除"-0",规定补码"10000000"为十进制的"-128".
3.(-128)没有相对应的原码和反码, (-128) = (10000000).

本文参考:
https://www.cnblogs.com/huangyb-blog/p/5684305.html
https://www.zhihu.com/question/20159860/answer/21113783 的第二个回答

阅读更多
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wn084/article/details/79963979
个人分类: java
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭