复习一个知识点——原、反、补码以及取反操作

一、相关概念

1.1  机器数与真值

  ·机器数  计算机中存储的数据都是带符号的二进制数,例如:5 → 0000 0101 , -5 → 1000 0101  此类数值称之为机器数。

  ·真值   为区别起见,将带符号位的机器数对应的真正数值称为机器数的真值。如:1000 0101的形式值为133,但它实际表示的值为-5,-5称之为真值。

1.2  原、反、补码

  ·原码  符号位加上真值的绝对值。如+5和-5的原码分别为:0000 0101和1000 0101

  ·反码  正数的反码是它本身,负数的反码是将它原码的符号位不变,其余各位按位取反。  如+5和-5的反码分别为:0000 0101和1111 1010

  ·补码  正数的补码是它本身,负数的补码是将它原码的符号位不变,其余各位按位取反再加1(其实就是反码+1)。如+5和-5分补码分别为:0000 0101和1111 1011

二、为何要用原、反、补码

2.1  符号位的问题

  我们已知正数的原、反、补码都是相同的,但对于负数来说确是完全不同。在处理加减乘除等运算时,若是人脑来进行,我们可以将符号位抽象出来然后直接操作真值即可。但若交由计算机完成,若还需提前去识别符号位,则会大大增加计算机基础电路的复杂度,故需要考虑带着符号位进行计算。

考虑一个1-1的问题:

·原码计算:1-1 = 1+(-1)= [0000 0001]原 + [1000 0001]原 = [1000 0010]原 =-2   结果显然不对

·反码计算:1-1 = 1+(-1)

        = [0000 0001]原 + [1000 0001]原

        = [0000 0001]反 + [1111 1110]反

        = [1111 1111]反

        = [1000 0000]原 = -0

  从结果来看,真值部分是对的,但0前面出现负号是无意义的。反而会引入1000 0000的机器码表示数值0,从而与0000 0000表示的0引起冲突,故而补码码应运而生。

·补码计算:1-1 = 1+(-1)

        = [0000 0001]原 + [1000 0001]原

        = [0000 0001]补 + [1111 1111]补

        = [0000 0000]补

        = [0000 0000]原 = 0

  可见,使用补码运算解决了符号位带入的问题和0的符号问题。值得注意的是,在补码的运算结果中,[1000 0000]补 代表的数值为-128,但由于该补码使用的是之前-0的补码,故-128是没有原码和反码表示的。有此也可以引申出,8位二进制值的原码或反码的表示范围为[-127,127],而补码的则为[-128,127]。

2.2  总结

  ·数字电路的CPU中仅实现了加法器,为实现减法器,减法都是通过转换为加法进行计算的。

  ·负数在计算机中是以补码的形式存储的,计算过程也是用补码实现的。

三、反码与取反

  初学时容易将两个概念混淆,前面已经提到,计算机中数据的存储和计算都是以反码的形式进行的。故取反这一过程也是围绕补码展开的,与反码这一概念并无关系。

看一个+5和-5取反的过程:

  +5 = [0000 0101]原 → [0000 0101]补 →按位取反→ [1111 1010]补 → [1000 0110]原 = -6

  -5 = [1000 0101]原 → [1111 1011]补 →按位取反→ [0000 0100]补 → [0000 0100]原 = 4

可见,对一个数取反都是先求得该数的补码,对补码进行按位取反,然后对结果再求补码即可。快速计算方法:对数a取反,结果为-(a+1)。

原文地址:https://www.cnblogs.com/jing-wen/p/9128699.html

时间: 2024-10-28 11:47:35

复习一个知识点——原、反、补码以及取反操作的相关文章

正负数取反的结果和规律

按位取反运计算方法原创 jackytse_ 最后发布于2012-10-29 14:27:01 阅读数 11247 收藏展开 读本文前请首先搞懂  “反码”,“取反”,“按位取反(~)”,这3个概念是不一样的. 取反:0变1,1变0 反码:正数的反码是其本身,对于负数其符号位不变其它各位取反(0变1,1变0) 按位取反(~): 这将是下面要讨论的. “~”运算符在c.c++.java.c#中都有,之前一直没有遇到这个运算符. 要弄懂这个运算符的计算方法,首先必须明白二进制数在内存中的存放形式,二进

逻辑取反技巧

在编码中,有时候要求当前的一个bool变量是true,但是随后要对他取反成false.一般我们用 bool ans=flag?false:true; 这样的语句来实现.但是今天我想到了一个更加好的办法,请看代码和测试: 代码: int b=-1; printf("%d\n",~b); if(b) puts("b is true"); b=0; if(~b) puts("~b is true"); 测试结果: 我们用int类型代替bool进行逻辑判

取反NOT ,汇编指令SETZ(SETE) SETNZ(SETNE)

//___逻辑取反 !______________________________________________________非零值取反得到0,      0取反得到1 int i, j;i  = 0x8877;j = !i; 反汇编代码: MOV DWORD PTR SS:[EBP-4], 0X4321XOR EAX, EAXCMP DWORD PTR SS:[EBP-4], 0SETE AL                                                

转载 原反补码

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

复习一个小知识点(反码与按位取反)

第一点是:反码与按位取反~ 在Java中~符号是按位取反,例如,~5=-6.-5=4.  快速计算:一般~可以直接用(a+1)算,正数负数均可 思路: 是按位取反运算,与反码是不同的,反码法规定,正数原反补码相同,负数的反码为原码除符号位以外取反.而按位取反运算中:正数取反是先将初始数值转换成二进制数(6==>00000110),再对二进制数的每一位取反:即将0变为1.将1变为0.(00000110==>11111001),得到的是最终结果的补码,要转换为最终结果的原码则需再次取补码,(此处一

标识符,进制转化,原反补码等

标识符 Java对包.类.方法.参数.变量等要素命名时使用的字符序列. 规则:***** 1.由字母(含中.英.日.俄等).数字.下划线_和美元符号$组成. 2.不能以数字开头   int 123a=1; 3.区分大小写  int a=1和int A=1是不一样的. 4.长度无限制.(一般编程长度不超过15个字符) 5.不能是Java中的保留字和关键字    int class="1"    int ainta=1 保留字和关键字都有哪些?我们知道以后应该避开它们. 标识符命名习惯:*

01、Java基础语法(常量、进制转换、原/反/补码、变量和数据类型)

1.常量 2.进制转换 3.原码.反码和补码 4.变量和数据类型 1.常量 常量:在程序执行过程中其值不发生改变. Java中常量的分类: 字面值常量: 自定义常量:(面向对象讲解,static final) 字面值常量的分类: 字符串常量:(用双引号引起来的内容, "HelloWorld") 整数常量:(所有整数,12,23) 字符常量:(用单引号引起来的内容,'A','1','中') 小数常量:(所有小数,3.14) 布尔常量:(只有true和false) 空常量null:(数组部

C语言实现原码补码输出

今天复习了一下C中的原码补码的知识,顺便编程使用for , while, do-while,goto,recursive 实现了补码和原码的输出. 核心思想: 借助一个字符串数组,将得到的原码和补码存储到相应数组中去.在计算原码的时候,由于存在负数的补码等于原码取反+1的这么一个关系,因而只要计算一个在计算机内部存贮着的补码就可以了.而获取补码的方式很简单,只需要依次做位与操作,逐个取出即可. ps: 这个版本的代码 可以很好的兼容 int short long等数据类型的输出 // =====

原码 补码

转载自   http://www.cnblogs.com/zhangziqiu/archive/2011/03/30/ComputerCode.html 有一天因为这个凌乱了 !是位反,~是按位反.如!P1_0和 ~P1 #include <iostream>using namespace std;int main(){ int p = 1; int t = !p; cout<<t<<endl; t = ~p; cout<<t<<endl; t