原码、反码、补码的理解与思考

原码、反码、补码都是二进制表示数的方式

原码
原码:首位为符号位,0表示整数,1表示负数,其余位表示数值,例如0011表示+3,而1011表示-3。
优点:符合人类阅读习惯,无论正数负数都能马上读出来
缺点:计算机做运算的时候不会把符号位提取出来,然后单独计算数值位的,而是把整个数包括符号位一起参与运算,于是就导致了
问题一:0011+1011=1110(-6)的错误计算结果。
问题二:0存在着两种表示方式。正零和负零的问题0000(+0)、1000(-0)

思考:如果世界上只有加法,没有减法;只有正数,没有负数。那么计算机直接使用原码也就没这些问题了。只是,我们的世界也许会枯萎,也许会干涸,但绝不会让你省心。

为什么会有原码,反码,补码?(有人说这是缘木求鱼,好像还真是)
众所周知,计算机采用二进制表示数。那么具体如何表示其中也是有学问的。原码是人类最直观想到的表现方式,但原码有缺点,于是产生了反码,也有缺点,最后产生了补码,相对完美,于是计算机系统大多使用补码来存储二进制数。反码的作用主要是方便原码到补码的过渡,方便理解。
前面说过,如果只有加法和正数,那么使用原码没有什么问题。之所以出现反码、补码,正是为了解决负数和减法所带来的问题。所以正数的原码、反码、补码都是一样的。

反码
反码:对原码进行“符号位不变,数值位取反”
例如:-3原码表示1011,反码就是1100;+3和-3的和就是0011+1100=1111,而1111正是0(原码1000的补码就是1111)。于是解决了问题一。
优点:满足绝对值相同的正负数相加值为零。可以把减法转换成加法
缺点:依然还有两种0的表示方式:0000(+0)和1111(-0)。
备注:反码只是求补码的过渡,不要纠结,为什么要给它一个名字,明明没什么用啊。

思考:反码解决了问题一,但还有问题二呢?
于是出现了补码。

为什么需要把减法转换成加法运算?
因为计算机电路设计发展中,为了简化电路设计,只保留了加法器,去除了减法器,将减法运算转换成对负数的加法运算以达成运算目的。

补码
补码:对原码进行“符号位不变,数值位取反”,再加一得到(对反码+1得到)
例如:-3的反码是1100,其补码就是1101。
反码中的0有两种表示方式:0000(+0)和1111(-0),把1111+1并舍弃高位溢出得到0000,这和0000(+0)的表示方式是一样的。
优点:解决了问题二,此时0只剩一种表示方式0000。同反码一样可以把减法转换成加法。
缺点:对人不易读。也算不上缺点,毕竟是给计算机读的。

问题:为什么负数总比正数多一个?
对于4位的原码,表示范围是:
[0111,1111],也就是[7,6,5,4,3,2,1,+0,-0,-1,-2,-3,-4,-5,-6,-7],2^4个,2^3-1个正数,两个0,和2^3-1个负数。

对于4位的反码,尽管负数的表示不同,但范围和原码是一致的
[7,6,5,4,3,2,1,+0,-0,-1,-2,-3,-4,-5,-6,-7]。

对于4位的补码,表示范围是:
[7,6,5,4,3,2,1,0,-1,-2,-3,-4,-5,-6,-7,-8],2^4个,2^3-1个正数,一个0,2^3个负数。
这是由于补码的规则决定的,因为没有反码通过+1可以得到补码1000。所以就人为规定了1000就是-8。这就是为什么负数比正数多一个的原因。

例子:
Integer.MAX_VALUE 2147483647
原码:0111 1111 1111 1111 1111 1111 1111 1111
反码:0111 1111 1111 1111 1111 1111 1111 1111
补码:0111 1111 1111 1111 1111 1111 1111 1111

Integer.MAX_VALUE的相反数 -2147483647
原码:1111 1111 1111 1111 1111 1111 1111 1111
反码:1000 0000 0000 0000 0000 0000 0000 0000
补码:1000 0000 0000 0000 0000 0000 0000 0001

Integer.MIN_VALUE -2147483648
int类型的最小值比较特殊,因为绝对值2147483648原码32位的int无法表示会高位溢出。
原码:没有
反码:没有
补码:1000 0000 0000 0000 0000 0000 0000 0000(人为规定)

思考:为什么最小的负数补码不能通过原码转反码再转补码的方法推算出来?
计算机教材里面都是这样的呀!其实从“取反”这样的运算来看,不符合人类思维常用的推导过程,这其实更像是计算机处理器运算的过程。因为“取反”在计算机中是相对高效的运算。
实际上数学的推导过程是先根据数值位数求“模”,然后求负数相对于该“模”的最小正同余数,就是负数的补码了。具体推导过程网络搜。之所以变了样,应该就是算法计算机化导致的,类似于乘法的计算机实现通常是左移位运算,除法通常是右移位运算。而计算机教材展示的是计算机实现该算法的原理,而不是数学推导原理。所以我们可能犯了一个错误:把算法的计算机实现原理当成了数学原理来学习了。

思考:如果确实如此,那我前面的思考过程不就成了扯淡了么?
上述过程可能不是原始的数学推导过程,但确实是计算机的处理流程。是具体的实现方法,何来扯淡一说!但我的思考:“先有原码,解决问题一得到反码,解决问题二得到补码”的逻辑就显得扯淡了。毕竟目的就是得到补码,根本不存在这演化过程,那么反码就更没存在意义了。

原文地址:http://blog.51cto.com/weijiancheng/2097083

时间: 2024-09-29 11:31:47

原码、反码、补码的理解与思考的相关文章

<13>【了解】计算机中的进制+【理解】原码反码补码基本概念+【理解】为什么要引入反码、补码?+【掌握】位运算符介绍及使用+位运算应用:编程实现10进制转2进制

1 #include <stdio.h> 2 3 int main(int argc, const char * argv[]) { 4 5 //定义10进制数,打印出10.8.16进制的值 6 int a = 13; 7 printf("%d\n",a); 8 printf("%o\n",a); 9 printf("%x\n",a); 10 11 //int 64 4个字节 12 int b = 0b0000000000000000

原码, 反码, 补码 详解

本篇文章讲解了计算机的原码, 反码和补码. 并且进行了深入探求了为何要使用反码和补码, 以及更进一步的论证了为何可以用反码, 补码的加法计算原码的减法. 论证部分如有不对的地方请各位牛人帮忙指正! 希望本文对大家学习计算机基础有所帮助! 一. 机器数和真值 在学习原码, 反码和补码之前, 需要先了解机器数和真值的概念. 1.机器数 一个数在计算机中的二进制表示形式,  叫做这个数的机器数.机器数是带符号的,在计算机用一个数的最高位存放符号, 正数为0, 负数为1. 比如,十进制中的数 +3 ,计

[转]原码, 反码, 补码 详解 很全

本篇文章讲解了计算机的原码, 反码和补码. 并且进行了深入探求了为何要使用反码和补码, 以及更进一步的论证了为何可以用反码, 补码的加法计算原码的减法. 论证部分如有不对的地方请各位牛人帮忙指正! 希望本文对大家学习计算机基础有所帮助! 一. 机器数和真值 在学习原码, 反码和补码之前, 需要先了解机器数和真值的概念. 1.机器数 一个数在计算机中的二进制表示形式,  叫做这个数的机器数.机器数是带符号的,在计算机用一个数的最高位存放符号, 正数为0, 负数为1. 比如,十进制中的数 +3 ,计

关于原码, 反码, 补码的复习

原本大一时考试90+的组成原理,隔了太长时间没使用,概念也慢慢模糊了,由于最近考试的基础知识有可能用到,于是,在网上找些资料,整理成这个文章,方便以后某天回来看看,好记性真不如烂笔头. 一. 机器数和真值 在学习原码, 反码和补码之前, 需要先了解机器数和真值的概念. 1.机器数 一个数在计算机中的二进制表示形式,  叫做这个数的机器数.机器数是带符号的,在计算机用一个数的最高位存放符号, 正数为0, 负数为1. 比如,十进制中的数 +3 ,计算机字长为8位,转换成二进制就是00000011.如

原码 反码 补码 以及 为什么要使用原码反码补码

原始博文网址,无意侵权,只是想记下来以后复习的时候方便, http://www.cnblogs.com/cumtchw/p/4523332.html http://www.cnblogs.com/zhangziqiu/archive/2011/03/30/ComputerCode.html 机器数 一个数在计算机中的二进制表示形式,叫做这个数的机器数,机器数是带符号的,在计算机中用一个数的最高位存放符号,正数为0,负数为1,比如,十进制中的+3,假设计算机字长为8位,转换成二进制就是0000 0

详解 原码, 反码, 补码

本篇文章讲解了计算机的原码, 反码和补码. 并且深入探求了为何要使用反码和补码, 以及更进一步论证了为何可以用反码和补码的加法计算原码的减法. 论证部分如有错误请各位牛人帮忙指正! 希望本文对大家学习计算机基础有所帮助! 一. 机器数和真值 在学习原码, 反码和补码之前, 需要先了解机器数和真值的概念. 1.机器数 一个数在计算机中的二进制表示形式,  叫做这个数的机器数.机器数是带符号的,在计算机中用一个数的最高位存放符号, 正数为0, 负数为1. 比如,十进制中的数 +3 ,计算机字长为8位

[转载]原码, 反码, 补码 详解

本篇文章讲解了计算机的原码, 反码和补码. 并且进行了深入探求了为何要使用反码和补码, 以及更进一步的论证了为何可以用反码, 补码的加法计算原码的减法. 论证部分如有不对的地方请各位牛人帮忙指正! 希望本文对大家学习计算机基础有所帮助! 一. 机器数和真值 在学习原码, 反码和补码之前, 需要先了解机器数和真值的概念. 1.机器数 一个数在计算机中的二进制表示形式,  叫做这个数的机器数.机器数是带符号的,在计算机用一个数的最高位存放符号, 正数为0, 负数为1. 比如,十进制中的数 +3 ,计

原码,反码,补码详解及 Java中&gt;&gt;和&gt;&gt;&gt;的区别

前两天分析 HashMap 的 hash 算法的时候,遇见了 >> 和 >>> 这两个符号,当时查了下资料,在脑子中过了一下.今天又碰到了,没想到竟然忘了  0-0........ 我这记忆力哎,不说了.只好做个笔记,提醒自己,遇到啥不会的最好记下来,好记性不如烂博客啊~ 既然涉及到位运算,我们追本索源,就先从最基础的原码,补码和反码学起.搜了一下这方面的资料,发现一篇专门介绍这方面的文章,写的很是透彻,便直接引用过来了,原文地址是:http://www.cnblogs.co

[转] 原码, 反码, 补码 详解

点击阅读原文 作者:张子秋出处:http://www.cnblogs.com/zhangziqiu/ 本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利. 本篇文章讲解了计算机的原码, 反码和补码. 并且进行了深入探求了为何要使用反码和补码, 以及更进一步的论证了为何可以用反码, 补码的加法计算原码的减法. 论证部分如有不对的地方请各位牛人帮忙指正! 希望本文对大家学习计算机基础有所帮助! 一. 机器数和真值 在学习

原码, 反码, 补码 详解(转)

http://www.cnblogs.com/zhangziqiu/archive/2011/03/30/ComputerCode.html 一. 机器数和真值 在学习原码, 反码和补码之前, 需要先了解机器数和真值的概念. 1.机器数 一个数在计算机中的二进制表示形式,  叫做这个数的机器数.机器数是带符号的,在计算机用一个数的最高位存放符号, 正数为0, 负数为1. 比如,十进制中的数 +3 ,计算机字长为8位,转换成二进制就是00000011.如果是 -3 ,就是 10000011 . 那