数字在计算机中的表示
本文最后更新于 464 天前,其中的信息可能已经有所发展或是发生改变。

基本概念


单位概念


(bit):计算机中最小的数字单位,是“二进制数字”(binary digit)的缩写,它只能取 $0$ 或 $1$ 两个值,因此bit被称作“二进制位”。

字节(byte):$8$ 个bit组成 $1$ 个字节(byte),通常也是计算机中最常见的数据大小单位,用于表示 $8$ 个二进制位的数字或字符。

在计算机中,一个bit指的就是一个二进制位,即最小的数字单位。


二进制表示


例如:

  • 在计算机中,$7$ 被表示为 $0000,0111$。其中,每四位加入 , 便于区分位数。

具体地:

  • $0000,0111$ 表示的二进制数字是 $00000111$。
  • 其中,前四位 $0000$ 表示十进制下的 $0$,后四位 $0111$ 表示十进制下的 $7$。
  • $0\times2^7+0\times2^6+0\times2^5+0\times2^4+0\times2^3+1\times2^2+1\times2^1+1\times2^0=7$
  • 该表示法将数字 $7$ 以二进制形式表示,并在前面补上了 $0$,使其达到了 $8$ 比特位(bits)的宽度,常常使用这种形式来表示计算机存储的二进制数。

按照上述过程,理论上一个字节(8个bit位)最大表示的数值范围为:

  • $0000,0000(0) \sim 1111,1111(255)$。

原码、反码、补码、移码


由于现实计算中不仅存在正数,还存在负数,因此按照上节中将一个字节中所有位都用来表示数是不合理的。

因此,在一些语言中区分了有符号数无符号数,像上节中表示的是无符号数的表示方法。


原码表示法


在使用原码表示法时,二进制数的最高位表示符号位,$0$ 表示正数,$1$ 表示负数。

以使用 $8$ 位二进制原码为例,表示 $-7$ 的二进制原码的步骤如下:

  • 将 $7$ 的二进制表示转换为 $8$ 位二进制数的原码: $0000,0111$。
  • 将该二进制数的符号位取反,即将第一位由“0”变为“1”,得到:$1000,0111$。

因此,在 $8$ 位二进制原码表示法中,$-7$ 的二进制原码为 $1000,0111$。

按照上述过程,在原码表示下,理论上一个字节(8个bit位)最大表示的数值范围为:

  • $11111,1111(-127) \sim 0111,1111(127)$。

需要注意,这种方式的缺点是正数和负数的加减法需要额外处理符号位,较为复杂。

例如计算:$-1 + 1 = 1000,0001 + 0000,0001 = 1000,0010(-2)$

怎么会是呢???显然是不对滴,因此我们又引入了反码。


反码表示法


反码是一种用于计算机中表示负数的二进制数表示法。在反码中:

  • 正数的反码与其原码相同;
  • 而负数则取其对应正数的原码每一位取反(0变为1,1变为0)得到。
  • 反码最高位仍作为符号位,0表示正数,1表示负数。

以使用 $8$ 位二进制原码为例,表示 $-7$ 的二进制反码的步骤如下:

  • 将 $7$ 的二进制表示转换为 $8$ 位二进制数的原码: $0000,0111$。
  • 将该二进制数的每一位取反,即将所有的位由“0”变为“1”,得到:$1111,1000$。

因此,在 $8$ 位二进制反码表示法中,$-7$ 的二进制反码为 $1111,1000$。

现在计算:$-1 + 1 = 1111,1110 + 0000,0001 = 1111,1111(反码)$

注意:反码直接计算的结果需要取反才能得到原码,因此对 $1111,1111$ 的非符号位全部取反得到 $1000,0000(-0)$。

显然是对的吧,数值是对了,但是出现了“+0”和“-0”的问题,依然不合理,因此我们最终引入了补码。


补码表示法


补码是一种计算机中表示有符号整数的二进制数表示法,也是一种将负数转化为正数的方法。在补码中:

  • 正数的补码与其原码相同;
  • 而负数则为其二进制反码加一。

以使用 $8$ 位二进制原码为例,表示 $-7$ 的二进制反码的步骤如下:

  • 将 $7$ 的二进制表示转换为 $8$ 位二进制数的原码: $0000,0111$。
  • 将每一位取反得到反码:$1111,1000$,然后末位 $+1$ 得到:$1111,1001$。

因此,在 $8$ 位二进制反码表示法中,$-7$ 的二进制补码为 $1111,1001$,由于 $-6$ 的二进制补码为 $1111,1010$,故我们将原本为 $1111,1000$ 表示为最小值 $-8$。

按照上述过程,在补码表示下,理论上一个字节(8个bit位)最大表示的数值范围为:

  • $1000,0000(-128) \sim 0111,1111(127)$

现在计算:$-1 + 1 = 1111,1111 + 0000,0001 = 1,0000,0000$,其中多出来的一位 $1$ 由于超过了补码的表示范围,故造成了溢出,最终的计算结果为 $0000,0000(0)$。

由此,我们通过补码可以将两个数的减法运算变为加法运算,但是由于符号位的存在,补码很难直接判断真值大小,因此引入移码的概念。


移码表示法


移码是一种为了方便计算二进制浮点数而设计的表示方法:

  • 将每个真值加上一个偏置值,再进行存储;
  • [ x ]_移 = 2^n + x (2^n > x \ge -2^n)

举例:

例如 $x$ 的真值为 $10100$:

$x = 10100,[ x ]_移 = 2^5+10100 = 1,10100(用,分割符号位)$

$-x = -10100,[ -x ]_移 = 2^5-10100 = 0,01100$

当 $x = 0$ 时:

[ +0 ]_ 移 = [ -0 ]_移

注意

  • 移码与补码只差一个符号位,符号位取反两者就能相互转换。

证明

  • 正数:$[ x ]_ 移 = 2^n + x$,相当于在第 $n$ 位 $+1$,即在符号位取反。
  • 负数:[ x ]_补 = 2^{n+1}+x = (2^n+x) + 2^n = [ x ]_移 + 2^n,也相当于符号位取反。

IEEE 754 标准


根据国际标准 IEEE 754,任意一个二进制浮点数 $V$ 可以表示成下面的形式:
V = (-1)^S \times M \times 2^E

  • $(-1)^S$ 表示符号位,当 $S=0$,$V$ 为正数;当 $S=1$,$V$ 为负数。
  • $M$ 表示有效数字,大于等于 $1$,小于 $2$,但整数部分的 $1$ 不变,因此可以省略。(例如尾数为 $1111010$,那么 $M$ 实际上就是$1.111010$,尾数首位必须是 $1$,$1$ 后面紧跟小数点,如果出现 $0001111$ 这样的情况,去掉前面的 $0$,移动 $1$ 到首位,随着时间的发展,IEEE 754标准默认第一位为 $1$,故为了能够存放更多数据,就舍去了第一位,比如保存 $1.0101$ 的时候, 只保存 $0101$,这样能够多存储一位数据)
  • $2^E$ 表示指数位。(用于移动小数点,所以说才称为浮点型)

比如, 对于十进制的 $5.25$ 对应的二进制为:$101.01$,相当于:$1.0101 \times 2^2$。所以,$S$ 为 $0$,$M$ 为 $1.0101$,$E$ 为 $2$。因此,对于浮点类型,最大值和最小值不仅取决于符号和尾数,还有它的阶码,所以浮点类型的大致取值范围:

  • 单精度:$±3.40282347 \times 10^{38}$
  • 双精度:$±1.79769313486231570 \times 10^{308}$

评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇