人有十个手指头,所以就有了十进制,满十进一。
计算机的存储单元受限于物理设备,只能有两种状态,即传统意义上的“开”和“关”,”高“和”低“,”1“和”0“,对计算机来说,二进制是它最擅长的。早期的计算机有尝试过用十进制存储和使用数据,但和二进制相比效率非常底下,后来这种方案被时代所抛弃了。此外二进制还和布尔代数相互映衬,有着坚实的理论基础。
机器数和真值
机器数
机器数:一个数在计算机中的实际存储形式。
机器数是带符号的,在计算机用一个数的最高位存放符号, 非负数为0, 负数为1。
如果用8位去表示一个数字,则十进制的3机器数为0000 0011;-3的机器数为1000 0011
如果用16位去表示一个数字,则十进制的3机器数为0000 0000 0000 0011;-3的机器数为1000 0000 0000 0011
真值
真值:机器数实际表示的值。
机器数的第一位为符号位,1代表负,0代表0或正。
例:0000 0011的真值为3;1000 0011 的真值为-3
原码, 反码, 补码
对于同一个机器码,可以有不同的理解方式。最初机器码是原码,后来又出现了反码和补码。
原码
正数的原码是其二进制本身;负数是符号位为1,数值部分取绝对值的二进制。
如果用8位去表示一个数字,则十进制3的原码为0000 0011;-3的原码为1000 0011
表示范围为[-127,127]。其中0有两种表示形式,0000 0000 (正零),1000 0000(负零)
反码
正数的反码和原码相同;负数是符号位为1,其它各位是原码取反。
如果用8位去表示一个数字,则十进制3的反码为0000 0011;-3的原码为1000 0011,反码为1111 1100
表示范围为[-127,127]。其中0也有两种表示形式,0000 0000 (正零),1111 1111(负零)
补码
正数的补码和原码相同;负数是符号位为1,其它各位是原码取反,未位加1。
如果用8位去表示一个数字,则十进制3的反码为0000 0011;-3的原码为1000 0011,补码为1111 1101
表示范围为[-128,127]。其中0只有一种表示形式 0000 0000 ,-128为1000 0000
运算过程
早期计算机设计时需要添加加减运算,加法可以利用微小电路单元加法器轻松实现。但是减法实现起来就没有那么容易了。考虑到减去一个正数等于加上一个负数,即: 1-1 = 1 + (-1) = 0 , 所以机器可以只有加法而没有减法, 也就不需要再为减法设计多余的电路了。
对于计算十进制的表达式: 1-1=0
原码计算
$$ 1 - 1 = 1 + (-1) = [00000001]原 + [10000001]原 = [10000010]原 = -2 $$
反码计算
$$ 1 - 1 = 1 + (-1) = [0000 0001]反 + [1111 1110]反 = [1111 1111]反 = [1000 0000]原 = -0\\ 2 + (-1) = [0000 0010]反 + [1111 1110]反 = [1,0000,0000]反 = (循环进位) [0000,0001] = 1 $$
补码计算
$$ 1-1 = 1 + (-1) = [0000 0001]补 + [1111 1111]补 = [0000 0000]补=[0000 0000]原 = 0 $$
原码计算结果为-2,与实际不符,故不能化减法为加法。
反码计算是由于-0的存在,可能需要循环进位,会让人很迷惑。
补码的出现解决了-0的问题,同时又能够多表示一个数-128。现代计算机一般使用原码。
同余
“模”的概念
想象日常使用的钟表,它可以显示0~12点的时间,假设现在是2点钟,请用手动拨动时针的方式将时间减4小时,你会怎么做?
有两种方式:
- 逆时针将时针拨4小时
- 顺时针将时针拨8(12-4)小时
拨动12-4也可以得到2,这里就涉及了同模的概念。
取模公式
$$ x\;\%\;y=x \; mod \; y =x-y\lfloor x/y \rfloor\quad for\; y\neq 0 $$
两个整数a,b,若它们除以整数m所得的余数(与m同号)相等,则称a,b对于模m同余
记作 a ≡ b (mod m),读作 a 与 b 关于模 m 同余。
例如4 mod 12 = 16 mod 12 = -8 mod 12 = 4
所以4,16,-8关于模12同余。
在模的范围内做减法,可以将“X-Y”的减法变更为“X+Y的补数“的加法
8位二进制数一共可以表示2的8次方,256个数,即0~255,他们的极限就是256,即256是8位二进制数的模。
假设有一个256刻度的时钟,当前时钟处于20,现在需要减去100,结果应该为-80。
用时钟方法,减去100就等价于加上156(256-100),结果为176,刚好与-80关于256同余。
为此可以得出正确的求补码方法:正数的补码为其本身,负数的补码为256-负数的绝对值。
取反加一
记得不太清楚了,好像是有这个公式。具体怎么解释这个公式,等想起来了再修改吧。
$$ ([原码]+[补码])\% 256 =1 $$
补码和原码的相互转化均为”取反加一“
”取反加一”和同模比起来更加好记,但是要记住补码的本质是什么。
参考
本文由 ukuq 创作,采用 知识共享署名4.0 国际许可协议进行许可
本站文章除注明转载/出处外,均为本站原创或翻译,转载前请务必署名
最后编辑时间为: Aug 3, 2019 at 10:28 pm