首页 > 其他分享 >原码、反码、补码知识点总结

原码、反码、补码知识点总结

时间:2022-10-31 16:34:28浏览次数:98  
标签:知识点 0000 0011 补码 反码 原码 1000


好久没接触这三个熟悉而陌生的概念,以前也没理解透彻这三个概念的真正含义与作用,现在来重新做一个清晰而简单的总结。

首先,原码、反码、补码只是机器中对于数字的三种不同的表示形式。下面说的数都默认为整数,关于小数的表示方法在本文中不做探讨。

机器数与真值

在机器中,往往以二进制来表示数字,这个数叫做机器数。为了区分正数和负数,则需要加入一位符号位来表示正负,而符号位便是第一位,其中0表示正数,1表示负数。

+1= [0000 0001]
-1= [1000 0000]
+3=[0000 0011]
-3=[1000 0011]

在上面用8位二进制表示的数中,真正用于表示数的,其实只有后面7位。因此机器数的形式值(如​​1000 0011=2^7 + 2^1 + 2^0=131​​​)不等于机器数的真值(如​​1000 0011=-000 0011=-2^1+2^0=-3​​​)。
即带符号位的机器数对应的真正的数值才被称为机器数的真值。

原码、反码、补码

可以看到,如果机器采用机器数进行计算,那么会存在两个明显的问题。其一,是0的表示存在歧义,即存在+0和-0两种表示方法;其二,是同一个数没法通过按位相加得到0,如​​(+1) + (-1) = [0000 0001] + [1000 0001] = [1000 0010]=-2​​。基于以上两个显著问题,提出了使用原码、反码、补码的思想。

原码

原码可以简单理解为上面所说的机器码,即一个符号位加上真值的绝对值。

+1= [0000 0001]
-1= [1000 0000]
+3=[0000 0011]
-3=[1000 0011]

反码

对于正数而言,原码=反码
对于负数而言,反码为保持符号位不变,其余位按位取反。
显然,反码的反码=原码

+3=[0000 0011]原=[0000 0011]反
-3=[1000 0011]原=[1111 1100]反

从下式可以看出,反码已经能使正负数进行正确的加法运算了,然鹅±0的情况依然存在。

(+3) + (-3) = [0000 0011]原 + [1000 0011]原 = [0000 0011]反 + [1111 1100]反 = [1111 1111]反 = [1000 0000]原 = -0

因此,为了解决±0的问题,需要引入补码。

补码

对于正数而言,原码=反码=补码
对于负数而言,补码=反码在最后一位加1
补码的补码=原码

+3=[0000 0011]原=[0000 0011]反=[0000 0011]补
-3=[1000 0011]原=[1111 1100]反=[1111 1101]补

在补码中,只会存在一个0的表示,即​​[0000 0000]补​​,即

(+3) + (-3) = [0000 0011]原 + [1000 0011]原 = [0000 0011]补 +[1111 1101]补 = [0000 0000]补 = [0000 0000]原 = 0

因此补码很好地解决了上述两个问题。同时,由于补码中不存在-0的表示,即​​[1000 0000]​​​,因此为了充分利用存储资源,​​[1000 0000]补​​成为了原码和反码中都不存在的一个值,即同样长度的表示中,补码比原码和反码能多表示一个数字。该数字的计算方式有点特殊,可以脑补给它转成原码时添加一位符号位以避免内存溢出(只是这么理解,实际并不会这样),将其进行求补运算以计算其原码,过程如下:

[1000 0000]补 =[1 1000 0000]补 (脑补加一位) = [1 0111 1111]反 = [1 1000 0000]原 = -[1000 0000]原 = -256

需要特别注意的是,上面1000 0000的原码和补码是相同的。

而同样用8位表示的正数,最大值为:

[0111 1111]原 = 255

因此使用补码后,负数会比正数多表示一个数。

C语言中int的最大最小值的十六进制表示

在理解清楚原码、反码、补码的基本知识后,可以看看C语言中的int的表示范围:

maxint = 0x7fffffff;
minint = 0x80000000;

首先要说明的是,在C语言中,或者说在内存中,十六进制的负数是以原码的形式保存的,而十进制的数字是以负数的形式保存的。
其中,​​​maxint​​​的表示为首位为0,其余全1,这是最大正数。
然而如果说十六进制的负数是原码存储,那么​​​minint​​​的表示为首位为1,其余全0,也就是前面所说的多出来的一位,即最小值-2147483648。
然鹅细心一点就会提出疑惑,​​​0x8000 0001​​​并不是-1,而是-2147483647。这么看起来似乎保存的不像是原码,更像是补码,毕竟它的补码是​​0xfffffffe​​​,而这个用二进制的计算方法计算其十进制就可以得到-2147483647了。所以可以理解成这也是存储为补码。
不过网上更广泛的解释是,​​​0x8000 0001​​​是对​​0x8000 0000​​加1,所以是-2147483647。两种解释见仁见智,但结果都是一样的。


参考资料

  1. ​​原码,补码和反码​​
  2. ​​关于0x80000000为什么等于-2147483648和负数在内存上储存的问题​​


标签:知识点,0000,0011,补码,反码,原码,1000
From: https://blog.51cto.com/u_15854687/5810312

相关文章

  • 关于前端面试你需要知道的知识点
    如何在ReactJS的Props上应用验证?当应用程序在开发模式下运行时,React将自动检查咱们在组件上设置的所有props,以确保它们具有正确的数据类型。对于不正确的类型,开发模......
  • C语言核心知识点大汇总
    C语言高级部分总结一、内存内存就是程序的立足之地,体现内存重要性。内存理解:内存物理看是有很多个Bank(就是行列阵式的存储芯片),每一个Bank的列就是位宽,每一行就是Words,则存......
  • 旋转矩阵知识点
    1、二维旋转矩阵的推导1.1、几何推导方式旋转矩阵(RotationMatrix)的推导-知乎(zhihu.com)     1.2、极坐标推导方式(7条消息)二维旋转......
  • 13个QA带你了解线上压测的知识点
    摘要:设计一个线上压测系统能让我们学习到多少东西?这13个问题看你能否搞定。本文分享自华为云社区《设计一个线上压测系统能让我们学习到多少东西?13个问题看你能否搞定》,作......
  • 13个QA带你了解线上压测的知识点
    摘要:设计一个线上压测系统能让我们学习到多少东西?这13个问题看你能否搞定。本文分享自华为云社区《​​设计一个线上压测系统能让我们学习到多少东西?13个问题看你能否搞定​......
  • Spring系列之零碎知识点
    ​​classpath​​​和​​classpath*​​​​classpath​​​和​​classpath*​​​区别:​​​classpath​​​:只会到你指定的class路径中查找找文件;​​​classpath*​......
  • java基础-->源码,反码,补码 和位运算
    原码、反码、补码原码:十进制数据的二进制表现形式,最左边的是符号位,0为正,1为负。反码:正数的反码是其本身,负数的反码是符号位保持不变,其余取反。补码:正数的补码是其本身,......
  • 1.天线知识点
    天线知识点1.天线实现宽带方法多谐振天线可以实现宽阻抗宽带。A.难点:如何产生或控制多个谐振点。常用的方法:多模辐射单元、多天线单元、电抗或寄生单元加载、阻抗变换......
  • JAVA常见基础知识点
    JAVA常见基础知识点一、注释Java中有三种注释,分别是单行注释、多行注释、文档注释。单行注释:注释某一行代码。使用//多行注释:注释某一段代码。使用/*...*/文档注释......
  • 【Java】来回顾下JWT知识点,了解一下什么是JWT?
    (回顾下JWT知识点)1.什么是JWT在介绍JWT之前,我们先来回顾一下利用token进行用户身份验证的流程:1.客户端使用用户名和密码请求登录。2.服务端收到请求,验证用户名和密码......