2026/3/26 3:08:57
网站建设
项目流程
五站合一网站建设,中国咖啡网站建设方案,抖音seo源码搭建,wordpress4.3 漏洞前言#xff1a;大家好#xff0c;我是你们的老朋友。
在上一章的学习中#xff0c;我们已经拥有了计算机的“上帝视角”#xff1a;我们知道了冯诺依曼架构下的五大金刚——运算器、控制器、存储器、输入设备、输出设备。我们知道主存储器#xff08;内存#xff09;里的…前言大家好我是你们的老朋友。在上一章的学习中我们已经拥有了计算机的“上帝视角”我们知道了冯·诺依曼架构下的五大金刚——运算器、控制器、存储器、输入设备、输出设备。我们知道主存储器内存里的MAR地址寄存器决定了能存多少个数据MDR数据寄存器决定了每个坑位能蹲多少个比特。但是那该死的求知欲在敲打着我们的脑壳“这些放在存储器里的数据到底长什么样”“为什么计算机非要用 0 和 1用 0-9 不香吗”“那个让我头秃的 16 进制到底有什么用”“为什么 0.3 这个小数在计算机里存不准”这就引出了第二章的核心主题——数据的表示和运算。这一章是整个计算机组成原理的“基石”。如果你连数字怎么表示都搞不清楚后面讲 ALU算术逻辑单元如何做加法、讲浮点数为什么会溢出时你绝对会一脸懵圈。本篇文章是基础希望能够帮助大家理解进位计数制的相关知识。一、从远古部落到罗马帝国——计数的演变1.1 最原始的“一维”计数法想象一下时光倒流回到几万年前的原始部落。你是部落里负责管果子的“仓库管理员”。今天大家出去干活带回来一堆苹果。你怎么记账那时候没有数字的概念你大概率会拿出石刀在墙壁上刻痕迹带回来一个苹果画一条竖线|。又带回来一个再画一条||。带回来五个画|||||。这种方法简单粗暴叫做“一维计数法” 。每一个符号竖线的权重都是一样的都代表“1”。但问题来了如果今天部落大丰收带回来 1000 个苹果难道你要在墙上画 1000 条线吗等你画完手断了墙也没地方了最关键的是当你想过来查账验证的时候还没等你数完数到第 382 个时候你估计就头晕眼花了还得从头数起。痛点总结所以单一符号无法高效表达大数值。1.2 罗马数字符号权重的诞生为了解决这个问题古人开始动脑子了“我们能不能用不同的符号代表不同数量的苹果”于是罗马数字诞生了。I代表 1。V代表 5。X代表 10。L代表 50C代表 100D代表 500M代表 1000。这时候如果你想记录 8 个苹果不用画 8 条线而是写成 VIII这个本质上其实就是加法这个就是5 1 1 1。如果你想记录 13 个苹果写成 XIII。这里出现了一个伟大的进步符号有了**权重Weight的概念。V的权重是 5I的权重是 1。把它们加起来就是数值。但是罗马数字依然有巨大的缺陷。想象一下你要算“一万”怎么办可能得发明个新符号叫W。要算“十万”呢再发明个Y。随着数字越来越大我们需要记忆的符号无穷无尽。更要命的是试着用罗马数字做个乘法MCMXCVI * XLII 这简直是反人类1.3 阿拉伯数字与“位权”的魔法真正拯救人类数学的是古印度人他们发明了阿拉伯数字没错阿拉伯数字是古印度人发明的阿拉伯人只是做了一回“快递员”把这个带入了欧洲。他们引入了两个核武器级别的概念有限的符号只有 0, 1, 2, … 9 这十个符号。位置决定权重位权同一个符号放在不同的位置代表的大小完全不同比如数字9755在个位权重是100110^011001它代表5×15 \times 15×1。7在十位权重是1011010^11010110它代表7×107 \times 107×10。9在百位权重是10210010^2100102100它代表9×1009 \times 1009×100。这就是进位计数制的精髓。我们不需要为“一万”发明新符号只需要把 1 写在万位上10000即可。1.4 为什么人类选择了十进制这是一个有趣的生物学巧合。你在教小孩子数数的时候是不是下意识地伸出手指“123… 10”。哎呀手指用完了怎么办这时候我们在地上放一块石头代表“一个十”然后手指收回去从头开始数。这就是**“逢十进一”**。因为人类有 10 根手指所以十进制成了最符合人类直觉的计数系统。所以如果《海绵宝宝》里的派大星要发明数学它会用几进制海绵宝宝和派大星每只手只有 4 根手指两只手加起来是 8 根。所以比基尼海滩的通用数学应该是八进制Octal在他们的世界里数到 7 之后下一个数就是 10代表十进制的 8。1.5 R 进制系统人类喜欢十进制但计算机不喜欢。计算机由亿万个晶体管组成对于一个电子元器件来说维持 10 种不同的稳定电压状态代表 0-9太难了很容易受干扰。但是区分**“通电”和“断电”**高电平/低电平却非常容易且稳定。通电 1断电 0这就注定了计算机只能生活在二进制的世界里所以我们可以将十进制的逻辑推广到任意进制R进制。每一个数码位所用到的不同的符号的个数就是所谓的基数。比如说十进制在每个数码位有可能用到的符号会有012一直到9总共有十种符号。那对于一个r进制的数来说它的奇数就应该是r也就是有可能会出现r种不一样的符号。核心概念基数Radix记作 r每个数码位上能使用的不同符号的个数。十进制 r10符号 0~9二进制 r2符号 0, 1八进制 r8符号 0~7十六进制 r16符号 0~9, A~F位权Weight第iii位的权重是rir^iri。任意进制转十进制的通用公式数值展开(KnKn−1...K1K0.K−1K−2...)r∑Ki×ri(K_n K_{n-1} ... K_1 K_0 . K_{-1} K_{-2} ...)_r \sum K_i \times r^i(KnKn−1...K1K0.K−1K−2...)r∑Ki×ri其中KiK_iKi是第iii位的系数具体的数字。rir^iri是第iii位的权。1.6 各种进制的常⻅书写⽅式后缀表示法二进制1010BBinary十六进制1652H 或 0x1652十进制1652DDecimal特殊前缀0x为十六进制专用前缀识别要点字母后缀具有最高优先级无标注时需结合上下文判断二、任意进制→\rightarrow→十进制按权展开法按权展开法是最简单的一种转换只要你会做乘法和加法就能搞定。核心思想就是把每一位上的数字乘以它对应的权重然后全部加起来。2.1 二进制转十进制【例题】将二进制数1101.1转换为十进制。解析我们先把每一位的“身份”列出来整数部分第 0 位个位是 1权重2012^0 1201第 1 位是 0权重2122^1 2212第 2 位是 1权重2242^2 4224第 3 位是 1权重2382^3 8238小数部分第 -1 位是 1权重2−10.52^{-1} 0.52−10.5计算过程Value1×231×220×211×201×2−1Value 1 \times 2^3 1 \times 2^2 0 \times 2^1 1 \times 2^0 1 \times 2^{-1}Value1×231×220×211×201×2−184010.5 8 4 0 1 0.584010.513.5 13.513.5快速心算技巧对于以下常见数据应该做到熟记于心尽量看一下就明白其的转化关系2012^0 12012122^1 22122242^2 42242382^3 823824162^4 16241625322^5 32253226642^6 642664271282^7 12827128282562^8 25628256(一个字节的最大值)21010242^{10} 10242101024(1K)看到1101你脑子里应该直接反应8 4 1 13。不要再去写公式了那是小学生的做法。2.2 八进制转十进制【例题】将八进制数5.4转换为十进制。解析5在个位权重8018^0 1801。4在小数位权重8−11/80.1258^{-1} 1/8 0.1258−11/80.125。计算Value5×14×0.12550.55.5Value 5 \times 1 4 \times 0.125 5 0.5 5.5Value5×14×0.12550.55.5这里有个有趣的现象八进制的0.4竟然等于十进制的0.5这也是为什么我们需要进制转换因为直觉往往会骗人。2.3 十六进制转十进制十六进制Hexadecimal是程序员的浪漫。因为二进制写起来太长了11111111写成十六进制FF就简洁得多。我们的阿拉伯数字符号只有九个不够用来表示16个基数怎么办我们使用字母来代替计算A 10B 11C 12D 13E 14F 15【例题】将十六进制数5.8转换为十进制。解析5在个位权重160116^0 11601。8在小数位权重16−11/160.062516^{-1} 1/16 0.062516−11/160.0625。计算Value5×18×0.062550.55.5Value 5 \times 1 8 \times 0.0625 5 0.5 5.5Value5×18×0.062550.55.5三、十进制→\rightarrow→任意进制最强算法如果想要把十进制数转化为任意进制数就稍微麻烦一点点但依旧很简单我们有一个很简单的方法请记住口诀整数除基取余小数乘基取整。3.1 整数转换除基取余法逆序原理假设我们要把十进制数XXX转为rrr进制。Xknrn...k1r1k0r0X k_n r^n ... k_1 r^1 k_0 r^0Xknrn...k1r1k0r0Xr×(knrn−1...k1)k0X r \times (k_n r^{n-1} ... k_1) k_0Xr×(knrn−1...k1)k0你看如果我们把XXX除以rrr商是括号里那一坨而余数恰好就是k0k_0k0最低位拿着商继续除以rrr得到的余数就是k1k_1k1。【例题】将十进制75转换为二进制。步骤短除法75÷23775 \div 2 3775÷237…… 余1(这是K0K_0K0最低位)37÷21837 \div 2 1837÷218…… 余118÷2918 \div 2 918÷29…… 余09÷249 \div 2 49÷24…… 余14÷224 \div 2 24÷22…… 余02÷212 \div 2 12÷21…… 余01÷201 \div 2 01÷20…… 余1(这是最高位)结果将余数**从下往上从高位到低位**书写1001011。3.2 小数转换乘基取整法顺序原理假设小数Y0.k−1r−1k−2r−2...Y 0.k_{-1} r^{-1} k_{-2} r^{-2} ...Y0.k−1r−1k−2r−2...Y×rk−1(k−2r−1...)Y \times r k_{-1} (k_{-2} r^{-1} ...)Y×rk−1(k−2r−1...)你看乘以rrr之后整数部分恰好就是k−1k_{-1}k−1小数点后第一位剩下的小数部分继续乘。【例题】将十进制0.3转换为二进制。步骤0.3×20.60.3 \times 2 0.60.3×20.6→\rightarrow→取整数0(这是K−1K_{-1}K−1)0.6×21.20.6 \times 2 1.20.6×21.2→\rightarrow→取整数1(注意取走整数1后剩下0.2)0.2×20.40.2 \times 2 0.40.2×20.4→\rightarrow→取整数00.4×20.80.4 \times 2 0.80.4×20.8→\rightarrow→取整数00.8×21.60.8 \times 2 1.60.8×21.6→\rightarrow→取整数1(剩下0.6)0.6×21.20.6 \times 2 1.20.6×21.2→\rightarrow→取整数1…死循环了你会发现0.6 再次出现了这意味计算进入了无限循环00110011...。结果将整数从上往下书写0.0100110011...** 高能考点警告**当然并不是所有的小数都能用二进制精确表示像 0.5 (2−12^{-1}2−1), 0.25 (2−22^{-2}2−2), 0.75 (0.50.250.50.250.50.25) 这种可以精确表示。但像 0.3, 0.1 这种在二进制里是无限循环小数。这就是为什么你在 Java 或 Python 里计算0.1 0.2结果往往不是0.3而是0.30000000000000004。这不是Bug这是进制转换的数学特性导致的精度丢失后续浮点数章节会详细讲。3.3 拼凑法高手必备在考场上画短除法太慢了。对于不太大的数我们可以用“减法拼凑”的思想。【例题】将260.75转换为二进制。整数部分 260找个最接近 260 的2n2^n2n是 256 (282^828)。260−2564260 - 256 4260−2564。找 4就是222^222。所以2602564260 256 42602564。在第 8 位和第 2 位填 1其他填 0。282^828(第9位) - 1… 00000 …222^222(第3位) - 121,202^1, 2^021,20- 0结果100000100小数部分 0.750.750.50.250.75 0.5 0.250.750.50.250.52−10.5 2^{-1}0.52−10.252−20.25 2^{-2}0.252−2结果.11总结果100000100.11这种方法熟练后速度比短除法快 3 倍以上四、二、八、十六进制的“特殊通道”为什么程序员偏爱 8 进制和 16 进制不仅仅因为它们短更因为它们和二进制之间存在完美的对应关系。八进制 (2382^38238)每3个二进制位对应1个八进制位。十六进制 (24162^4162416)每4个二进制位对应1个十六进制位。4.1 二进制↔\leftrightarrow↔八进制转换规则以小数点为界整数向左每3位一组小数向右每3位一组。不足补0。【例题】二进制11110.10转八进制。分组整数11 110→\rightarrow→补零变成011 110011 3110 6小数.10→\rightarrow→补零变成.100100 4结果36.4(八进制通常写作36.4836.4_836.48或36.4O36.4O36.4O)4.2 二进制↔\leftrightarrow↔十六进制转换规则同理4位一组。【例题】二进制111100.101转十六进制。分组整数11 1100→\rightarrow→补零0011 11000011 31100 12 (对应 C)小数.101→\rightarrow→补零.10101010 10 (对应 A)结果3C.A(十六进制通常写作0x3CA或3CAH) 常见误区提示补零的方向千万别搞反整数是在最左边补010变成010值不变。小数是在最右边补00.1变成0.10值不变。如果你在整数右边补010变成100那就相当于乘以2了大错特错五、真值与机器数最后我们来聊两个概念为后面的章节做铺垫。5.1 真值 (True Value)就是我们人类书写的、带有正负号的数字。 比如15,-8,0.5。 这是给人看的符合人类习惯。5.2 机器数 (Machine Number)是数字在计算机里的实际存储形式。 计算机里没有和-号怎么办用 0 和 1 代替通常规定0 代表正1 代表负。这一个表示符号的位放在数字的最前面叫做符号位。比如真值-5(二进制101)。 如果不考虑复杂的编码原反补简单地把符号位加上去符号位1(负)数值位101机器数可能长这样1101但实际上计算机为了方便做减法运算发明了原码、反码、补码、移码。这些让人头大的概念我们将在下一篇博客中详细拆解。结语文章的最后给基础不好的同学或者觉得枯燥的同学讲个好玩的事。你知道吗德国的大数学家莱布尼茨微积分的发明者之一被认为是现代二进制的发明者。但当他看到中国的《易经》八卦图时震惊得下巴都掉了。太极生两仪阴–和 阳—。这不就是 0 和 1 吗两仪生四象太阴、少阳、少阴、太阳。这不就是 00, 01, 10, 11 吗四象生八卦乾、坤、震、巽… 每一卦由三根爻组成。坤卦全是阴爻000(0)乾卦全是阳爻111(7)所以咱们的老祖宗早在几千年前就已经悟出了二进制的真谛。不管是算命先生掐指一算还是程序员敲击键盘本质上我们都在玩弄 0 和 1 的艺术。