计算机真值、原码、反码、补码、移码

本文深入解析了计算机中数字的各种表示方法,包括真值、原码、反码、补码和移码的概念及相互转换。重点阐述了补码在计算机运算中的作用,以及移码在浮点数表示中的应用。

1.概念介绍

首先,我们假设机器存储数字字长是8位。

直接使用表格举例说明概念和计算方式:

概念例1例2例3例4例5例6转换关系
真值(十进制)+0-0+5-5+0.5-0.5十进制形态下的数字
真值(二进制)+0-0+101-101+0.1-0.1二进制形态下的数字
原码000000001000000000000101100001010100000011000000首位是符号位,0正,1负,其他7位存实际值
反码000000001111111100000101111110100100000010111111

正数的反码=原码;

负数的反码是原码符号位不变,其他位取反

补码000000001000000000000101111110110100000011000000

正数的补码=反码=原码;

负数的补码是反码符号位不变,末位加1

移码(增码)100000000000000010000101011110111100000001000000

无论正负数,

移码=补码的符号位取反,其他位不变

2.详细介绍

真值:无须多说,就是通常我们数学意义上理解的数字;

原码:计算机对数字的定点表示法,首位0或1来表示正或负,其他位来表示数值绝对值大小,通过真值的二进制求解可以直接得到原码数值位的编码;

反码,也是计算机对数字的定点表示法,通常当做原码求补码或补码求原码的中间值;

补码,同样也是计算机对数字的定点表示法,通常,计算机内存中数字的表示方法都是按照补码存储,引入补码的目的,是为了计算机方便对数字进行运算,举例说明:

假设计算机存的是原码,那么:

5 + (-5) = 00000101 + 10000101 = 10001010 = -10

按位相加明显不是正确的,但如果不按位相加,那势必需要用更复杂的逻辑运算,进而提升了计算机硬件开销和设计复杂性;而利用补码做运算,刚好能解决这个问题:

5 + (-5) = 00000101 + 11111011 = 00000000 = 0

我们看到,补码按位相加,高位溢出丢弃后,结果值再根据补码求原码,就能得出值为0,这个结果显然才符合预期;

移码:用补码表示阶码的时候,当阶码无限小,产生了下溢的时候,阶码变成了0,那么这个浮点数的值变为了1,而实际上这个数是无限接近于零,所以引入移码是用来解决浮点数中阶码的问题,规则是,用移码数减1表示阶码,下面用一个例字说明移码在浮点数中的应用:

例:java中用float可以表示浮点数,总共32位,其中首位表示数字的正负,紧接着的8位表示阶码,剩下23位表示尾数精度部分

00000000 00000000 00000000 00000000

我们上面说到,数字在内存中的表示通常按照补码表示,但在浮点数表示里面,只有尾数精度部分才会用补码,而指数部分用移码来表示

我们来算一个数字,如 12.625

整数部分12转为二进制为:1100

小数部分123转为二进制位:101

合并后:1100.101

按照科学计数法的二进制指数形式表示为:1.100101x2^11,其中1.100101是尾数,100101是尾数精度部分,11为指数。

尾数精度部分100101用补码值转为float中23位存储:10010100000000000000000

指数11,补码为 00000011,移码为10000011,移码减1为10000010,放入float阶码位置

最后结果为0 10000010 10010100000000000000000

计算结果可以用java方法验证:Integer.toBinaryString(Float.floatToIntBits(f))

 

 

 

 

### 原码反码补码移码的定义 #### 定义说明 原码是一种最简单的二进制表示方法,其特点是符号位明确区分正负数。对于正数,符号位为`0`,数值部分直接用二进制表示;而对于负数,符号位为`1`,数值部分同样保持不变[^3]。 反码是对原码的一种转换形式。对于正数而言,反码与其原码完全一致;而针对负数,则需将其数值部分按位取反得到反码[^2]。 补码进一步改进了反码的形式,在处理负数时更加高效。具体来说,正数的补码即为其本身,而负数的补码可通过对其反码加一获得。 移码主要用于浮点数中的阶码表示,它通过将真值加上一个偏置量来实现无符号化存储。通常情况下,该偏置量等于\(2^{n-1}\),其中\(n\)代表总位数。 --- ### 数值范围分析 #### 原码的数值范围 假设机器字长为 \( n \) 位(含一位符号位),则: - 正数的最大值为 \( (2^{n-1} - 1)_\text{十进制} \) - 负数的最小值为 \( -(2^{n-1} - 1)_\text{十进制} \) 因此,原码能够表示的整数范围为:\[ -(2^{n-1}-1) \sim +(2^{n-1}-1) \][^3] 值得注意的是,存在两个零值分别对应于 `+0` 和 `-0` 的不同编码方式。 #### 反码的数值范围 同理,当考虑 \( n \)-bit 字长时, - 对应正数最大仍可达至 \(+(2^{n-1}-1)\), - 针对负数情况亦可低达 \(-(2^{n-1}-1)\). 所以反码所能覆盖的整体区间同样是:\[-(2^{n-1}-1),+(2^{n-1}-1)\]. 同样地,这里也存在着两种不同的零表达形式(+0,-0)[^4]. #### 补码的数值范围 利用补码体系下, - 最大正值依旧维持在 \(+(2^{n-1}-1)\); - 不过由于引入了一种额外状态用于填补原本由单独 "-0" 占据的位置,使得现在可以达到更低限度直到 \(-2^{n-1}\). 最终得出结论:采用这种机制之后整个可用空间变为连续闭合区域:[\-2^(n−1)..2^(n−1) −1],并且解决了关于双重零表述的问题.[^4] #### 移码的数值范围 考虑到移码实际上是基于补码基础上增加固定偏移量的结果,故此如果原始补码支持从-\(2^{n-1}\)到+\((2^{n-1}-1)\)之间变化的话,那么相应调整后的实际显示效果就会是从0一直到\(2^n-1\). 这意味着每一个可能产生的组合都被赋予了一个独一无二非重复性的呈现形态. 综上所述,给定任意长度N比特的情况下,我们有如下关系成立: \[ [-(2^{n-1})..(2^{n-1}-1)]_{补码} → [(0)..(2^n-1)]_{移码}. \] --- ```python def range_summary(n_bits): max_positive = (2 ** (n_bits - 1)) - 1 min_negative_original_complement = -(2 ** (n_bits - 1)) result = { 'Original Code': f'{-max_positive} to {max_positive}', 'Complementary Code': f'{min_negative_original_complement} to {max_positive}', 'Offset Binary': f'{abs(min_negative_original_complement)} to {(2**n_bits)-1}' } return result print(range_summary(8)) ``` 上述代码展示了如何根据不同编码方案计算并总结它们各自的数值范围。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值