计算机如何存储和表示数字: 二进制。
二进制
- 存储单位
MB
,GB
,TB
等。 - 正数,负数,整数,浮点数的表示。
- 美国信息交换标准代码 -
ASCII
,用来表示字符。 -
UNICODE
1992年诞生,是字符编码标准,解决ASCII
不够表达所有语言的问题。
二进制中,一个1
或0
叫 一位
(a bit).
8位能表示的最小数字是0, 8位都是0;最大数是255,8位都是1.
能表示256个不同的值,2的8次方.
8位是如此常见,以至于有专门的名字:字节.
1 字节 = 8 位(1 bytes = 8 bits)
MB(Mege是百万字节)
, GB(Giga是十亿字节)
, TB(8万亿个1和0)
等,不同前缀代表不同数量级。
1千字节 = 2的10次方 = 1024字节
1000也是千字节(KB)的正确单位,也就是1000
和1024
都是正确单位。
32位/64位计算机: 是一块块处理数据,每块是32位或64位。
32位能表示的最大数是:43亿左右。(32个1)。
现在图片都是用32位颜色
。
正数,负数,整数,浮点数的表示
负数,大部分计算机用第一位表示正负:1是负,0是正。用剩下的31位来表示数字。能表示的数字范围是:正 20亿 到 负 20亿
64位能表示最大数是正负9.2 * 10 ^ 18
计算机必须给内存中每一个位置,做一个“标记”,这个标记叫“位址(ADDRESSES)”,目的是为了方便存取数据。
非整数,常见浮点数。有很多种表示,最常见的是 IEEE 754标准。它用类似科学记数法的方法,来存取十进制值。例如: 625.9 = 0.6259 * 10 ^ 3
, .6259
叫“有效位数”, 3
是“指数”。
在32位浮点数中,第1位表示数字的正负,接下里8位存指数,剩下32位存有效位数。
ASCII
与其用特殊方式来表示字母,计算机可以用数字表示字母,最直接的方法是给字母编号。
设计于1963年,ASCII是7位代码,足够存储128个不同值。可以表示大写字母,小写字母,数字0-9,特殊符号以及标点符号。
Unicode
解决ASCII
不够表达所有语言的问题。
最常见的Unicode
是16位,有超过一百万个位置。
- 对所有语言的每个字符都够了
- 100多种字母表加起来占了12万个位置,还有位置放数学符号,甚至Emoji,就像ASCII用二进制来表示字母一样。
- 其它格式,比如MP3或GIF,用二进制编码声音/颜色,表示照片,电影,音乐。
这些标准归根到底是一长串位。
短信,视频,互联网上的每个网页,甚至操作系统,只不过是一长串1和0。
算术逻辑单元
- ALU,英特尔74181
- ALU有2个单元,1个算术单元和1个逻辑单元
- 算术单元: 半加器(处理1个bit,2个输入)。 全加器(处理1个bit,3个输入)。8 bit 加法(1个半加器,7个全加器)
- 逻辑单元:检测数字是否为0的电路(一堆OR门最后加一个NOT门),ALU抽象成V符号,Flag标志(是否相等,是否小于,是否溢出等等)
表示和存储数字是计算机的重要功能,但真正的目标是计算,有意义的处理数字。
处理数字的操作由计算机的“算术逻辑单元(ARITHMETIC & LOGIC UNIT)”处理,称之为: ALU
- 是计算机的数学大脑
- 计算机里负责运算的组件,基本其它所有部件都用到了ALU
英特尔74181:
第一个封装在单个芯片内的完整ALU。
布尔逻辑,做一个简单的ALU电路功能和 74181差不多。
ALU单元
ALU有2个单元,1个算术单元和1个逻辑单元。
算术单元:
负责计算机里所有的数字操作,比如加减法,比如某个数字+1(增量运算)。
计算根本“把两个数字相加”,可以用单个晶体管一个个拼,把这个电路做出来,但很快就会复杂到难以理解。所以会使用更高层的抽象,用逻辑门来做。
最简单的加法电路,是拿2个bit加在一起(bit是0或1),有2个输入:A和B,1个输出:就是两个数字的和。需要注意的是:A,B,输出,这3个都是单个Bit(0或1),输入只有四种可能。
0 + 0 = 0
1 + 0 = 1
0 + 1 = 1
二进制里,1与true相同,0与false相同。
这组输入和输出,和XOR门的逻辑完全一样。
1 + 1 = 10
使用XOR
门不够表示,需要一根额外的线代表“进位”。只有输入是1和1时,进位才是“true”,因为算出来的结果用1个bit存不下,可以和AND
门一齐使用,构成半加器
半加器/全加器
两个输入 A 和 B都是1位,两个输出 “总和”与“进位”。
如果想处理超过1 + 1的运算,需要“全加器”。
101
101
----
1010
意味着,算下一列的时候,还有之后的每一列,得加3位在一起,并不是2个。
半加器:输出了进位。
有3个输入:A,B,C(都是1个bit)
所以,最大的可能是:1 + 1 + 1
“总和”1,“进位”1,所以要二条输出线: “总和”和“进位”。
可以用 半加器 做 全加器:
先用半加器将 A 和 B 相加,然后把C输入到第二个半加器,最后用一个OR门检查进位是不是true。
可以再提升一层抽象,把全加器作为独立的组件。全加器会把A,B,C三个输入加起来,输出“总和”和“进位”。
独立组件:
使用独立组件,可以相加两个8位数字。
如果第9为有进位,代表着2个数字的和太大了,超过了8位,叫做“溢出”。
一般来说“溢出”的意思是,两个数字的和太大了,超过了用来表示的位数,这会导致错误和不可预期的结果。
著名的例子是:吃豆人,用8位存当前关卡数。如果玩到了第256关,ALU会溢出,造成一连串错误和乱码,使得该关卡无法进行。
避免溢出,可以加更多的全加器,可以操作16或32位数字。让溢出更难发生,但代价是更多逻辑门,另外一个缺点 ,每次进位都要一点时间。如今的量级是每秒几十亿次运算,所以会造成影响。所以,现代计算器用的加法电路有点不同,叫“超前进位加法器”。它更快,做的事情是一样的:把二进制数相加。
ALU的算术单元,也能做一些其它数学运算,一般支持这8个操作:
- ADD 加法
- ADD WITH CARRY 带进位的加法
- SUBTRACT 减法
- NEGATE
- INCREMENT 增量(+1)
- DECREMENT 减量(-1)
- SUBTRACT WIH BORROW 带借位的减法
- PASS TUROUGU 数字无改变通过
就像加法器一样,这些操作也是由逻辑门构成。
没什么魔法,只是更多逻辑门。
逻辑单元(LOGIC UNIT)
逻辑单元执行逻辑操作,AND
, OR
, NOT
操作。
也能做简单的数值测试。比如一个数字是不是负数。
检查ALU输出是否为0的电路:
使用一堆OR门检查其中一位是否为1,哪怕只有一个Bit(位)是1,就知道那个数字肯定不是0,然后用一个NOT门取反。所以只有输入的数字是0,输出才为1。
只是一大堆逻辑门巧妙的连接在一起。
特殊符号来表示ALU:
8位ALU有两个输入,A和B,都是8位(bits),还需要告诉ALU执行什么操作,例如加法或减法,所以用4位的操作代码告知ALU,简言之,"1000"可能代表加法命令,"1100"代表减法命令。
操作代码告诉ALU执行什么操作,输出结果是8位的,ALU还会输出一堆标志(FLAG),“标志”是1位的,代表特定状态。比如相减两个数字,结果为0。
ALU常用标志:
- OVERFLOW(BIT) 是否溢出
- ZERO(BIT) 是否相等
- NEGATIVE(BIT) 是否负数
计算机是怎样在没有齿轮或杠杆的情况下进行运算?
- 晶体管
- 二进制
- 逻辑门
- ALU(算术单元和逻辑单元): 逻辑与算术
计算机需要一些“记忆”。
寄存器和内存
Memory (存储 / 内存 两种含义)
- 存1位(Gated Latch - 锁存器)。
- 存8位(Register - 寄存器)。
- 16 * 16 的矩阵存256,数据选择器/多路复用器(Multiplexer)解码8位地址,定位单个锁存器。
- 4位代表行,4位代表列。
- 组合256位内存 + 多路复用器。
- 可寻址的256字节内存。
- 8个模块,每个模块有32个小方块,每个小方块有4个小块,每个小块是128位 * 64 位。
通过ALU计算出来的结果,需要找地方存储,可能还需要进行多个连续操作。这就用到计算机内存了。
电脑用的是“随机存取存储器”,简称“RAM”。它只能在有电的情况下存储东西,比如游戏状态。
另外一种存储(memory)叫持久存储,电源关闭时数据也不会丢失。
锁存器
目前看到的电路都是单向的,总是向前流动。
回向电路,把输出连回输入。
OR
门输出连回输入:
"0 OR 0"是0,所以电路输出0。
如果将A变成1, "1 OR 0" 为1,所以输出1,连回输入回到B, OR 门看到的是两个输入都是1。
"1 OR 1"仍然为1,所以输出不变。
如果A变成0,OR门依然输出1。
AND
门输出连回输入:
"1 AND 1",永远输出1.
如果A设为0,由于是AND门,输出会变成0. 这个电路能记录0。
OR
门连回能存1的电路AND
门连回能存0的电路
为了做出有用的存储(memory),需要把两个电路结合起来:
它有两个输入,"设置"输入,把输入变成1,"复位"输入,把输出变成0。
如果"设置"和"复位"都是0,电路会输出最后放入的内容。也就是,它存储了1位的信息。
这叫做锁存,因为它“锁定”了一个值,放入数据的动作叫做“写入”,拿出数据的动作叫做“读取”
简化一个输入:
将它设为0或1,来存储值,还需要一根线来“启用”内存。启用时允许写入,没启用时就“锁定”。
在此基础上,加一些额外的逻辑门,可以做出“门锁”电路。因为门可以打开和关上
把“门锁”放到盒子里,这个盒子能存一个bit:
一切从0开始,数据输入从0换到1,从1换到0。
不管输入1还是0,输出值都是0,因为允许写入线是关闭的,所以内容不会变化。
打开“允许写入线”输入1,“打开”门,输入数据是1,1就能在门锁存起来,输出也是1。现在关闭掉“允许写入线”,输出会保持1。不管输入数据是什么,输出都是1。
寄存器
并排放8个锁存器,可以存8位信息,比如一个8 bit数字。
寄存器能存一个数字,这个数字有多少位,叫“位宽”。
写入寄存器前,要先启用里面所有锁存器。
- 可以用一根线连接所有“允许输入线”,把它设位1。
- 然后用8条数据线发送数据
- 然后将“允许写入线”设为0
- 就可以将8 bit 存储起来
64位寄存器要64根数据线,64根连到输出端。只要1根线启用所有锁存器,但加起来也有129根线了。
如果256位寄存器要513根线。解决方法是矩阵
在矩阵中,不并列排放锁存器,而是做成网格,存256位,用16 * 16 网格的锁存器,有16行16列。
要启用某个锁存器,就打开相应的行线和列线。
打开交叉的锁存器的“允许写入线”,所有其它的锁存器,保持关闭。
可以增加AND
门,只有行线和列线均为1,AND
门才输出1.
所以可以用选择单个锁存器,这种行/列排列法,用一根“允许写入线”连所有锁存器,为了让锁存器变成“允许写入”,行线,列线和“允许写入线”都必须是1,每次只有1个锁存器会这样,代表可以只用一根“数据线”连接所有锁存器来传数据。因为只有一个锁存器会启用,只有那个会存数据。其它锁存器会忽略数据线上的值,因为没有“允许写入”。
“允许读取线”来读数据,从一个指定的锁存器,读取数据。所以对于256位的存储,只要35根线。1条“数据线”,1条“允许写入线”,1条“允许读取线”,还有16行16列的线用于锁存器(16 + 16 = 32, 32 + 3 = 35)。
需要某种方法来 唯一指定 交叉路口。
多路复用器
将地址转成 行 和 列,需要“多路复用器”。
多路复用器有不同大小,因为有16行,需要1到16多路复用器。
工作方式:
输入一个4位数字,它会把那根线,连接相应的输出线。如果输入0000,它会选择第一列,如果选择输入0001,会选择下一列,以此类推。
一个多路复用器处理(row), 另外一个多路复用器处理列(column)。
把256位内存当成一个整体,它输入一个8位地址:4位代表列,4位代表行,还需要“允许写入线”和“允许许读取线”。还需要一条数据线,用于读/写数据。256位内存,也没法做事情,所以还需要扩大规模。把它们并排放置。
并排放置,一行8个,可以存一个8位数字,8位也叫做一个字节(byte),为了存一个8位数字,同时给8个256位内存一样的地址。每个地址存1位,意味着下图总共能存256个字节(byte)
不看作是一堆独立的存储模块和电路,而是看成一个整体的可寻址内存。每个地址能读或写一个8位值。
现代的计算机的内存扩展到上兆字节(MB)和千兆(GB)的方式,不断把内存打包到更大规模,随着内存地址增多,内存地址也必须增长。
8位最多能代表256个内存地址(11111111 是255, 0~255,一共256个数字),要给千兆或十亿字节的内存寻址,需要32位的地址。
8个模块
内存的一个重要特性是:可以随时访问任何位置。
“随机存取存储器”,简称RAM
:
RAM
就像人类的短期记忆,记录当前在做什么事。
把内存中某块放大,看到32个内存方块;放大其中一个方块,可以看到有4个小块;如果再放大,可以看到存“位”的矩阵,这个矩阵是128 * 64位,总共是8192位。
每个方格4个矩阵,所以一个方格有32768(8192 * 4 = 32768)位(bits)。
一共32个方格,一个芯片大约存100万(8192 4 32 = 1048576)位。RAM
有8个芯片,所以总共800万位,也就是1兆字节(1 MB)
用锁存器完成了一块SRAM
(静态随机存取存储器),还有其它类型的RAM
,例如闪存和NVRAM
,它们在功能上与SRAM
相似,但用不同的电路存单个位。比如用不同的逻辑门,电容器,电荷捕获或忆阻器。但根本上,这些技术都是矩阵层层嵌套,来存储大量信息。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。