从零开始给女朋友讲计算机 1 - 从比特、字节、补码到 ASCII、GB2312、Unicode
起因
在代码 review 的过程中,总是发现有人在数据类型转换(reinterpret_cast)、大小端的问题(什么情况下需要考虑大小端,什么情况下不需要考虑)上犯错误,究其原因是没有彻彻底底地搞懂数据的二进制表示。我想写篇文章,用通俗易懂的语言把这件事情说明白,通俗易懂到我希望我的小白女友也能看懂。于是我就尝试着先做些铺垫,给她讲了些基础。发现效果出奇的好,于是赶紧把这一过程记录如下。
0 和 1 的世界
计算机的世界只有 0 和 1,所有的数据都由 0 和 1 的组合:数字、字母、汉字、图片、音乐、电影、游戏、网页等都可以由很多的 0 和 1 组成。
计算机如何知道一长串的 0 和 1 是什么含义呢?
比如 0100 0001
可能表示数字 65,可能表示大写字母A
,可能和更多的 0 和 1 共同组成一个汉字,也可能表示图片上某个点的颜色,其意义完全取决于人们约定的规则。
比特和字节
正着说:每一个 0 和 1 叫做一个比特(bit),8 个比特组成一个字节(Byte)。字节是计算机的基本单位,通常计算机一次最少处理一个字节。
例如:人们常说的一个 Word 文档 100 KB,一张图片 2 MB,一首歌 10 MB,一部电影 4 GB,内存 8 GB,硬盘 512 GB 等等。这里的大“B”就是 Bytes,字节。
比特(bit)最常见于宽带的宣传:例如 500M 宽带的完整单位是 500 Mbps(注意这里是小“b”,不是大“B”)。bps 即 bits per second,500Mbps 指的是每秒最大传输 500 兆比特(bit)。所以 500M 的宽带最快下载速度不是 500 MB/s,而是 500/8 = 62.5 MB/s。
反着再说一次:一个字节(byte)有 8 个比特(bit);每个比特只能是 0 或 1,8 个比特一共有 2^8 = 256 种组合,可以代表 256 种含义(具体含义完全取决于人们约定的规则)。
数字的二进制表示:用 0 和 1 表示数字
首先想到用 8 个比特表示 0-255:人们约定,高位到低位每个 bit 有不同的权重,代表不同的值,如此便可用 8 个 bit 表示 0-255 的所有数字。
高位 -> 低位 | bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 |
---|---|---|---|---|---|---|---|---|
权重 | 128 | 64 | 32 | 16 | 8 | 4 | 2 | 1 |
举例:0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
举例:35 | 0 | 0 | 1 | 0 | 0 | 0 | 1 | 1 |
举例:65 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 1 |
举例:128 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
举例:255 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
对于这种不考虑负数的情况,我们称之为无符号数。
那如何表示一个负数(有符号数)?
有很多种方法,只要约定好一个规则即可。比如我们可以约定,最高位 bit7 代表符号位,0 代表正数,1 代表负数。于是一个字节,8 个 bit 可以表示 -127 ~ 127 的数字。注意其中 0 有两种表示,+0 和 -0。
高位 -> 低位 | bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 |
---|---|---|---|---|---|---|---|---|
权重 | +/- | 64 | 32 | 16 | 8 | 4 | 2 | 1 |
举例:+0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
举例:-0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
举例:35 | 0 | 0 | 1 | 0 | 0 | 0 | 1 | 1 |
举例:-65 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 1 |
举例:127 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
举例:-127 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
现实计算机世界的负数几乎都是补码表示。和无符号数的规则的差别仅在最高位的权重为负。于是一个字节,8 个 bit 可以表示 -128 ~ 127 的数字。注意其中 0 只有一种表示。
高位 -> 低位 | bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 |
---|---|---|---|---|---|---|---|---|
权重 | -128 | 64 | 32 | 16 | 8 | 4 | 2 | 1 |
举例:0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
举例:35 | 0 | 0 | 1 | 0 | 0 | 0 | 1 | 1 |
举例:65 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 1 |
举例:-128 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
举例:127 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
举例:-127 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
举例:-1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
先停一下
看到这里,如果问你,1 0 0 0 0 0 0 0 代表一个什么数字,你要怎么回答?千万别急着回答,回答之前应该先问清楚,要按照什么规则去解析。比如这串 0/1 表示的是一个无符号数还是一个补码表示的有符号数。
如何表示更大的数?比如 10000
用多个字节表示。一个字节不够就两个,两个不够就三个、四个甚至八个十六个,直到够用!用 2 个字节就能够表示 0 - 65535 之间的无符号数,用 4 个字节就能表示 0 - 4294967295 的无符号数!
高位 -> 低位 | bit 15 | bit 14 | bit 13 | bit 12 | bit 11 | bit 10 | bit 9 | bit 8 | bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
权重 | 32768 | 16384 | 8192 | 4096 | 2048 | 1024 | 512 | 256 | 128 | 64 | 32 | 16 | 8 | 4 | 2 | 1 |
举例:0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
举例:65 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 1 |
举例:255 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
举例:10000 | 0 | 0 | 1 | 0 | 0 | 1 | 1 | 1 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 |
举例:40256 | 1 | 0 | 0 | 1 | 1 | 1 | 0 | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 |
举例:60666 | 1 | 1 | 1 | 0 | 1 | 1 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 0 | 1 | 0 |
有符号数(补码)也是类似的,只不过最高位的权重为负。用 2 个字节就能够表示 -32768 - -32767 之间的有符号数,用 4 个字节就能表示 -2147483648 - 2147483647 的有符号数!
直接使用上面的表格(二进制表示的 bit 15 到 bit 0 和上面一模一样),但是现在按照补码的规则进行解析(最高位权重为负),于是得到的结果就不一样了。
高位 -> 低位 | bit 15 | bit 14 | bit 13 | bit 12 | bit 11 | bit 10 | bit 9 | bit 8 | bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
权重 | -32768 | 16384 | 8192 | 4096 | 2048 | 1024 | 512 | 256 | 128 | 64 | 32 | 16 | 8 | 4 | 2 | 1 |
举例:0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
举例:65 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 1 |
举例:255 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
举例:-25280 | 1 | 0 | 0 | 1 | 1 | 1 | 0 | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 |
举例:-4870 | 1 | 1 | 1 | 0 | 1 | 1 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 0 | 1 | 0 |
十六进制:二进制的简化表示法
二进制要用 8 个 0/1 表示一个 byte,太不方便,为简化表示,十六进制用分别用一个 0-F 表示一个字节的前 4 位和后 4 位。一般还会加上前缀0x
,以提醒读者后面是 16 进制表示法。
如何表示带小数点的数(浮点数)?
还是一样,只要约定好一个规则就行。计算机界流行的浮点数规则是 IEEE 定义单精度浮点(4 字节表示)和双精度浮点(8 字节表示)。具体规则比较复杂,不在这里展开。
如何表示字符?
我们可以约定,0000 0001 代表 a,0000 0002 代表 b,以此类推。从 0000 0000 到 1111 1111 的 256 种组合中表示 a-z、A-Z,加上各种标点符号也是绰绰有余。现实计算机世界几乎都心照不宣地采用 ASCII 规则来表示常见的英文字符、标点以及一些不显示的控制字符等。ASCII 只用了 7 个 bit。
进制 | 十进制 | 十六进制 | 字符/缩写 | 解释 |
---|---|---|---|---|
00000000 | 0 | 00 | NUL (NULL) | 空字符 |
00001010 | 10 | 0A | LF/NL(Line Feed/New Line) | 换行键 |
00001101 | 13 | 0D | CR (Carriage Return) | 回车键 |
00100000 | 32 | 20 | (Space) | 空格 |
00100001 | 33 | 21 | ! | |
00101100 | 44 | 2C | , | |
00101110 | 46 | 2E | . | |
00110000 | 48 | 30 | 0 | |
00110001 | 49 | 31 | 1 | |
00110010 | 50 | 32 | 2 | |
01000000 | 64 | 40 | @ | |
01000001 | 65 | 41 | A | |
01000010 | 66 | 42 | B | |
01000011 | 67 | 43 | C | |
01011000 | 88 | 58 | X | |
01011001 | 89 | 59 | Y | |
01011010 | 90 | 5A | Z | |
01100001 | 97 | 61 | a | |
01100010 | 98 | 62 | b | |
01100011 | 99 | 63 | c | |
01111000 | 120 | 78 | x | |
01111001 | 121 | 79 | y | |
01111010 | 122 | 7A | z | |
01111111 | 127 | 7F | DEL (Delete) | 删除 |
如何表示汉字?
一个字节一共就 256 种排列组合,就算每个组合代表一个汉字,也只能表示 256 个汉字,这显然是不够的。要想表示一个汉字,至少需要 2 个字节。这样就有 2^16 = 65536 种排列组合,可以表示 65536 个汉字了。应对常见的汉字已经不成问题。GB2312 编码就是用两个字节给汉字编码的。具体编码规则网上找得到,这里不详细展开。
如何表示韩文、日文、阿拉伯文等所有字符?
每个国家、地区都有自己的编码方式。比如同样的一串数字 1011 0000 1010 0001 在GB2312 编码下代表汉字“啊”,而在某种日文编码规则中则可能代表一个日文字符。
比如一个日本程序员开发了一个软件,在日文编码的机器上可以正常显示日文,但是如果拿到中文编码的机器上就会显示乱码。为解决这一问题,推出了 Unicode 编码。Unicode 采用 4 字节编码,可以表示 2^32 = 4294967295 个字符,足够容纳目前世界上所有已知的字符了,甚至包括各种 emoji 表情!
总结
计算机的世界由 0/1 组成,数字、字母、图片等等所有信息都由一串串的 0/1 表示。8 个比特组成一个字节,字节是计算机的基本单位。一个字节可以表示 2^8 = 256 种含义,如何解析完全取决于人们约定的规则。如果一个字节不足以表示所有的范围、可能性,就用多个字节表示。
从零开始给女朋友讲计算机 1 - 从比特、字节、补码到 ASCII、GB2312、Unicode的更多相关文章
- Java 第十一届 蓝桥杯 省模拟赛 计算机存储中有多少字节
计算机存储中有多少字节 题目 问题描述 在计算机存储中,12.5MB是多少字节? 答案提交 这是一道结果填空的题,你只需要算出结果后提交即可.本题的结果为一个整数,在提交答案时只填写这个整数,填写多余 ...
- 我给女朋友讲编程html系列(4) -- html常用简单标签
今天似乎有点感冒,浑身无力,在操场上躺了半个小时,好了许多.好了,废话不说了,还是写今天的教程吧. 1,html中的换行标签是 br,写法是: <br /> 2,html中有一些特殊的字符 ...
- 萌新web前端从零开始(1)——计算机入门
前言:这是一个萌新从零开始的学习之路,与大家分享自己的看法与见解,还请指出错误与遗漏点方便改正. 1.认识计算机. 计算机语言常见的有C,PHP,Ruby,Java,C#,Basic,JS,C++等, ...
- 我给女朋友讲编程总结建议篇,怎么学习html和css
总共写了11篇博客了,7篇讲html的,4篇讲网络的.不敢说写的多么好吧,最起码的是我迈出了写作的第一步,写作的过程中了解了一些其他的知识,比如SEO.几种重定向等,由于个人能力和见识有限,写出来的东 ...
- 我给女朋友讲编程html系列(3) --html中的超链接标签-a标签 和 框架frame与框架集frameset
我们浏览网页的时候,当单击某段文字或图片时,就会打开一个新的网页,这里面就使用了超链接. 就比如下图是一个导航类网页,当你单击某个链接就会打开新的网页. 比如,我拿我的qq空间“金河访谈”举例,新建一 ...
- 我给女朋友讲编程html系列(2) --Html标题标签h1
Html是一门标签语言,因此学习Html最快的方式就是学习使用html标签. html标题标签:h1,h2,h3,h4,h5,h6 标题标签总共有6个,h1,h2,h3,h4,h5,h6,从h1到h6 ...
- 我给女朋友讲编程html系列(1) -- Html快速入门
Html是一门编写网页的语言. 在我学习Html的时候,网上的很多朋友说,直接使用[记事本]编写就行了,最后保存为后缀名为 .html 的文件. 不过,我建议你用[Nodepad++]来编写网页,用这 ...
- 北京大学Cousera学习笔记--3-计算导论与C语言基础-第一讲.计算机的基本原理-计算机怎么计算-数的二进制
思考问题 1.“数”在计算机中是如何表示的? 2.逻辑上“数”是怎么运算的? 3.物理上“数”的计算是怎么实现的? 从图灵机计算问题得出: 1.字母表中的符号越多(几进制),读入移动次数减少,但程序数 ...
- 我给女朋友讲编程CSS系列(3) CSS如何设置字体的类型、大小、颜色,如何使用火狐浏览器的Firebug插件查看网页的字体
一.CSS如何设置字体的类型.大小.颜色 设计网页时,一般设置body的字体,让其他标签继承body的字体,这样设置特别方便,但是标题标签h1到h6和表单标签(input类型)是没有继承body的字体 ...
随机推荐
- EVE-NG 入门教程 (Mac OSX BIg Sur)
EVE-NG 入门搭建指南 1. 什么是 EVE-NG EVE-NG (Emulate d Virtual Environment) 是一个可以运行虚拟主机.网络设备的模拟器,目前该软件分为了社区版. ...
- MindSpore循环神经网络
MindSpore循环神经网络 一. 神经网络的组成 神经元模型:首先简单的了解以下构成神经网络的最基础单元:神经元.每个神经元与其它神经元相连,处于激活状态时,就会向相连的神经元发送相应信号.从而改 ...
- CPU消耗,跟踪定位理论与实践
CPU消耗,跟踪定位理论与实践 一.性能指标之资源指标定位方案 1.打tprof报告方法 抓取perfpmr文件 60秒. perfpmr.sh 60 从结果文件中取出tprof.sum 或直接抓取t ...
- 2D池化IPoolingLayer
2D池化IPoolingLayer IPooling层在通道内实现池化.支持的池类型为最大, 平均 和 最大平均混合. 层描述:二维池化 使用张量上的2D滤波器计算池化a tensor A, of d ...
- TVM中的调度原语
TVM中的调度原语 TVM是一种用于高效内核构造的领域专用语言. 本文将展示如何通过TVM提供的各种原语来调度计算. from __future__ import absolute_import, p ...
- 【Java实现】剑指offer53.1——在排序数组中查找数字(LeetCode34:在排序数组中查找元素的起始位置)
序数组中查找元素的起始位置):思路分享 <剑指offer>题目和LeetCode主站本质是一样的,想要找到target数目,也需要找到左右边界 题目解析: 在一个排序数组中,找到targe ...
- 深入理解java虚拟机笔记Chapter3-垃圾收集器
垃圾收集器 垃圾收集(Garbage Collection,GC),它的任务是解决以下 3 件问题: 哪些内存需要回收? 什么时候回收? 如何回收? 本节补充知识: ① s:Survivor区 新生代 ...
- Rethinking Training from Scratch for Object Detection
Rethinking Training from Scratch for Object Detection 一. 概述 正常训练目标检测的流程分为以下几种: 在imagenet上进行预训练,然后在特定 ...
- 【NX二次开发】获取视图当前的剪辑边界UF_VIEW_ask_current_xy_clip()
UF_VIEW_ask_current_xy_clip()这个函数网上还没有详细的说明,我花了一点时间,详细得理解了一下函数返回的4个值的意思,作为一个猜想,希望有人能验证一下. 获取视图当前的剪辑边 ...
- 【dp】动归总结
原标题:[DP专辑]ACM动态规划总结 转载自 http://blog.csdn.net/cc_again?viewmode=list http://blog.csdn.net/cc_again/ar ...