計(jì)算機(jī)中數(shù)值和字符串怎么用二進(jìn)制表示?
大家好,我是呼嚕嚕。我們都知道現(xiàn)代計(jì)算機(jī)采用 0 和 1 組成的二進(jìn)制,來(lái)表示所有的信息。那大家是不是有時(shí)候會(huì)有這些疑問:為什么計(jì)算機(jī)采用了二進(jìn)制?二進(jìn)制是如何表示計(jì)算機(jī)的相關(guān)信息的?比如數(shù)字、字符串、聲音、圖片、視頻等等
進(jìn)制
進(jìn)位計(jì)算法是一種常見的計(jì)算方式,常見的有十進(jìn)制,二進(jìn)制,十六進(jìn)制
- 十進(jìn)制
十進(jìn)制,都是以0-9這九個(gè)數(shù)字組成,不能以0開頭, 逢十進(jìn)一。十進(jìn)制是我們從小就潛移默化般學(xué)習(xí)的,我們大多數(shù)人擁有的手指或腳趾的數(shù)目就是10,天生讓我們適合十進(jìn)制為基礎(chǔ)的數(shù)字系統(tǒng)
- 二進(jìn)制
二進(jìn)制,數(shù)字中只有 0 和 1,逢二進(jìn)一
- 八進(jìn)制
八進(jìn)制,數(shù)字0-7,逢八進(jìn)一
- 十六進(jìn)制
十六進(jìn)制,數(shù)字有 0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F組成,逢十六進(jìn)一。其表示形式比較特殊,因?yàn)?0~15不能用數(shù)字來(lái)展示,所以強(qiáng)制規(guī)定:10 用 A 表示、11 用 B 表示、12 用 C 表示、13 用 D 表示、14 用 E 表示、15用F表示
進(jìn)制間的轉(zhuǎn)換
- R進(jìn)制 → 十進(jìn)制:按權(quán)展開
- 十進(jìn)制 → R進(jìn)制:整數(shù)小數(shù)分開處理
- 整數(shù)部分的轉(zhuǎn)換方法是:“除基取余,上右下左”。即用要轉(zhuǎn)換的十進(jìn)制整數(shù)去除以基數(shù)R,將得到的余數(shù)作為結(jié)果數(shù)據(jù)中各位的數(shù)字,直到余數(shù)為0為止。上面的余數(shù)(先得到的余數(shù)) 作為右邊低位上的數(shù)位,下面的余數(shù)作為左邊高位上的數(shù)位。
- 小數(shù)部分的轉(zhuǎn)換方法是:“乘基取整,上左下右”。即用要轉(zhuǎn)換的十進(jìn)制小數(shù)去乘以基數(shù)R,將得到的乘積的整數(shù)部分作為結(jié)果數(shù)據(jù)中各位的數(shù)字,小數(shù)部分繼續(xù)與基數(shù)R相乘。以此類推,直到某步乘積的小數(shù)部分為0或已得到希望的位數(shù)為止。最后,將上面的整數(shù)部分作為左邊高位上的數(shù)位,下面的整數(shù)部分作為右邊低位上的數(shù)位。
我們需要注意的是:在轉(zhuǎn)換過(guò)程中,可能乘積的小數(shù)部分總得不到0,即轉(zhuǎn)換得到希望的位數(shù)后還有余數(shù),這種情況下得到的是近似值。
- 二進(jìn)制轉(zhuǎn)八進(jìn)制、十六進(jìn)制
由于把二進(jìn)制的三位看成一個(gè)整體就是八進(jìn)制的數(shù),二進(jìn)制的四位也就是十六進(jìn)制的數(shù)。通過(guò)這個(gè)規(guī)律,我們很容易地就能實(shí)現(xiàn)二進(jìn)制與八進(jìn)制、十六進(jìn)制的相互轉(zhuǎn)換。整數(shù)部分從低向高每3或4位數(shù)用一個(gè)等值八/十六進(jìn)制數(shù)替換,不足時(shí)高位補(bǔ)0;小數(shù)部分從高向低每3或4位數(shù)用一個(gè)等值八或十六進(jìn)制數(shù)替換,不足時(shí)低位補(bǔ)0
- 八進(jìn)制、十六進(jìn)制 轉(zhuǎn)二進(jìn)制
每一位數(shù)改成等值的3或4位二進(jìn)制數(shù),整數(shù)部分高位0省略;小數(shù)部分低位0省略
計(jì)算機(jī)為什么使用二進(jìn)制?
我們從小更熟悉十進(jìn)制的運(yùn)算,0、1、2、3、4、5、6、7、8、9十個(gè)數(shù)字,逢十進(jìn)一。但是計(jì)算機(jī)中使用二進(jìn)制,只有0和1兩個(gè)數(shù)字,逢二進(jìn)一。
采用二進(jìn)制的原因:
- 二進(jìn)制在自然界中最容易被表現(xiàn)出來(lái)。自然界中二值系統(tǒng)非常多,電壓的高低、水位的高低、門的開關(guān)、電流的有無(wú)等等都可以組成二值系統(tǒng)。
- 計(jì)算機(jī)使用二進(jìn)制和現(xiàn)代計(jì)算機(jī)系統(tǒng)的硬件實(shí)現(xiàn)有關(guān)。制造二個(gè)穩(wěn)定態(tài)的物理器件容易,使得組成計(jì)算機(jī)系統(tǒng)的邏輯電路通常只有兩個(gè)狀態(tài),即開關(guān)的接通與斷開。由于每位數(shù)據(jù)只有斷開與接通兩種狀態(tài),因此二進(jìn)制的數(shù)據(jù)表達(dá)具有抗干擾能力強(qiáng)、可靠性高的優(yōu)點(diǎn)
- 二進(jìn)制非常適合邏輯運(yùn)算,可方便地用邏輯電路實(shí)現(xiàn) 算術(shù)運(yùn)算
機(jī)器數(shù)和真值
機(jī)器數(shù)
一個(gè)數(shù)在計(jì)算機(jī)中的二進(jìn)制表示形式, 叫做這個(gè)數(shù)的機(jī)器數(shù)、機(jī)器碼。由于我們平時(shí)不僅使用的是正數(shù),還有大量的負(fù)數(shù),而計(jì)算機(jī)是無(wú)法識(shí)別符號(hào)"+","-", 所以計(jì)算機(jī)規(guī)定,用二進(jìn)制數(shù)的最高位0表示正數(shù),如果是1則表示負(fù)數(shù)。機(jī)器數(shù)是帶符號(hào)的
如果十進(jìn)制中的數(shù) +3 ?,計(jì)算機(jī)字長(zhǎng)為8位,轉(zhuǎn)換成二進(jìn)制的機(jī)器數(shù)就是0000 0011?。如果是-3?,就是 10000011
真值
帶符號(hào)位的機(jī)器數(shù)對(duì)應(yīng)的真正數(shù)值是 機(jī)器數(shù)的真值,我們知道機(jī)器數(shù)的第一位是符號(hào)位, 比如1000 0011?直接轉(zhuǎn)換成十進(jìn)制為131?,但實(shí)際上最高位1 是負(fù)號(hào),其真正的值為 [-3]
機(jī)器數(shù)的編碼形式有哪些?
原碼
原碼就是符號(hào)位加上真值的絕對(duì)值, 即用最高位表示符號(hào), 其余位表示值
比如如果是8位二進(jìn)制:
- [+1] = (0000 0001)原
- [ -1] = (1000 0001)原
我們?nèi)祟惛鶕?jù)二進(jìn)制的規(guī)則,可以一眼就明白原碼代表的數(shù)字,方便了人類
面試的時(shí)候有一個(gè)經(jīng)典的問題:8位二進(jìn)制數(shù)原碼的取值范圍是?我們只需將除了最高位,用來(lái)表示符號(hào),其他位都是1,即[1111 1111 , 0111 1111],換算成十進(jìn)制:[-127 , 127]
那n位二進(jìn)制數(shù)呢?
取值范圍:
image-20221129211701296
現(xiàn)在看起來(lái)都是那么美好,然而當(dāng)我們將正負(fù)數(shù)相加時(shí),遇到了問題:2個(gè)[+1]?相減 ,其實(shí)就相當(dāng)于[+1]? 和 [-1]? 相加,我們的預(yù)期是0?, 但計(jì)算機(jī)實(shí)際上計(jì)算時(shí):(0000 0001)原+(1000 0001)原=(1000 0010)原 =[-2]
為了解決這個(gè)問題,反碼就應(yīng)運(yùn)而生了
反碼
反碼主要是針對(duì)負(fù)數(shù)的,正數(shù)的反碼是其本身,負(fù)數(shù)的反碼是在其原碼的基礎(chǔ)上, 符號(hào)位不變,其余各個(gè)位取反
- [+1] = (0000 0001)原 = (0000 0001)反
- [-1] = (10000001)原 = (1111 1110)反
反碼如果是表示的一個(gè)正數(shù),那我們還是一眼就能知道他的數(shù)值,但如果是負(fù)數(shù)的反碼時(shí),我們就需要轉(zhuǎn)換成原碼才能看出它的真值。如果最高位有進(jìn)位出現(xiàn),則要把它送回到最低位去相加(循環(huán)進(jìn)位)的
- [- 1] = (1000 0001)原 = (1111 1110)反
- [+7] = (0000 0111)原 =(0000 0111)反
- [-1] + [+7] = (1111 1110)反 +(0000 0111)反= (1 0000 0101)反 = (0000 0110)反 =[+ 6]
2個(gè)正數(shù)相減:[+1] - [+1] = [+1] + [-1] = (0000 0001)反 + (1111 1110)反 = (1111 1111)反 =(1000 0000)原 = [-0]這樣就完美實(shí)現(xiàn)了“正負(fù)相加等于0",但奇怪的是 ,這個(gè)[-0]是有符號(hào)的,這就要?dú)w因于 原碼的設(shè)計(jì)之初,存在的問題,
- (1000 0000)原=[- 0]
- (0000 0000)原=[+0]
對(duì)的,你沒看錯(cuò),零竟然有2個(gè),習(xí)慣計(jì)算機(jī)的萬(wàn)事萬(wàn)物一一對(duì)應(yīng),嚴(yán)謹(jǐn)認(rèn)真的工程師們表示無(wú)法接受,得想辦法去掉[-0],最后他們就發(fā)現(xiàn)了神奇的補(bǔ)碼
補(bǔ)碼
補(bǔ)碼的規(guī)則:針對(duì)負(fù)數(shù)繼續(xù)改進(jìn)了思路:正數(shù)的補(bǔ)碼就是其本身。負(fù)數(shù)的補(bǔ)碼是在其原碼的基礎(chǔ)上, 符號(hào)位不變, 其余各位取反, 最后一位+1。即在反碼的基礎(chǔ)上最后一位+1
[+1] = (0000 0001)原 = (0000 0001)反 = (0000 0001)補(bǔ)
[-1] = (1000 0001)原 = (1111 1110)反 = (1111 1111)補(bǔ)
[+1] - [+1] = [+1] + [-1] = (0000 0001)補(bǔ) + (1111 1111)補(bǔ) = (1 0000 0000)補(bǔ) = (0000 0000)補(bǔ) = [0]如果補(bǔ)碼在補(bǔ)一位1的時(shí)候,發(fā)生最高位進(jìn)位,會(huì)自動(dòng)丟掉最高位。期間引用了計(jì)算機(jī)對(duì)符號(hào)位的自動(dòng)處理,利用了最高位進(jìn)位的自動(dòng)丟棄實(shí)現(xiàn)了符號(hào)的自然處理。
那(1000 0000)補(bǔ)? 那現(xiàn)在表示多少?-128
- (1000 0000)補(bǔ) =-1 * 2^7 =[-128]
- (1011)補(bǔ) = -1 * 2^3 + 02^2 + 12^1 + 1*2^0 = -5
- (0011)補(bǔ) = 0 * 2^3 + 02^2 + 12^1 + 1*2^0 =3
如果是8位二進(jìn)制, 使用原碼或反碼表示的范圍為[-127, +127], 而使用補(bǔ)碼表示的范圍為[-128, 127],使用補(bǔ)碼還能夠多表示一個(gè)最低數(shù)
補(bǔ)碼其實(shí)脫胎于 模運(yùn)算系統(tǒng):比如一天中的24小時(shí)是一個(gè)模運(yùn)算系統(tǒng),任意時(shí)刻的鐘點(diǎn)數(shù)都是0到23間的一個(gè)整數(shù),這有點(diǎn)類似24進(jìn)制
- 今天的第24點(diǎn),就是明天的0點(diǎn);
- 今天的25點(diǎn),就是明天的凌晨1點(diǎn);
- 今天的-4點(diǎn),就是昨天的20點(diǎn),我們稱20是-4對(duì)模24的補(bǔ)碼,模就是容量、極值的意思
再舉個(gè)例子:鐘表上的12個(gè)刻度也是一個(gè)模運(yùn)算系統(tǒng)。假定時(shí)鐘現(xiàn)在指向10,要把指針只向6,有兩種方法
- 倒撥4格:10 - 4 = 6
- 正撥8格:10 + 8 = 18 = 6 (mod 12)
所以模12系統(tǒng)中 -4 = 8 (mod 12),我們稱8是-4對(duì)模12的補(bǔ)碼
一個(gè)模運(yùn)算系統(tǒng)中:一個(gè)負(fù)數(shù)可以用它的正補(bǔ)數(shù)(負(fù)數(shù)的補(bǔ)碼)代替,一個(gè)負(fù)數(shù)的補(bǔ)碼 = 模 - 該負(fù)數(shù)的絕對(duì)值
那我們之前公式 一個(gè)負(fù)數(shù)的補(bǔ)碼 = 符號(hào)位不變, 其余各位取反, 最后一位+1,是怎么來(lái)的?
負(fù)數(shù)的原碼 取反 再加1, 這只是方便大家記憶的手段,實(shí)際上它相當(dāng)于加一個(gè)模256也就是2^8,為什么要拆,這是由于8位機(jī),8位2進(jìn)制數(shù),至能表示0~255個(gè)數(shù),一共256個(gè)數(shù),所以它是表示不了256這個(gè)值的,只能是255+1。由于計(jì)算機(jī)系統(tǒng)里面不僅只有正數(shù),還有負(fù)數(shù)呢,這個(gè)該怎么表示?計(jì)算機(jī)大師就想到了,可以將256個(gè)數(shù)一分為二,規(guī)定最高位為符號(hào)位,最高位1開頭的表示為負(fù)數(shù),最高位0開頭表示正數(shù)。我們這里需要注意一下,特殊的0,所以8位2進(jìn)制數(shù)表示范圍就變成了[-128,127],這個(gè)范圍是不是很熟悉!
[-1] = (1000 0001)原 = (1111 1110)反 = (1111 1111)補(bǔ)?,如果符號(hào)位參與計(jì)算,(1111 1111)補(bǔ) 的十進(jìn)制 等于 255 。而255 + |-1|= 256?,也就是模。補(bǔ)碼本天成,妙手偶得之
小結(jié)一下:
- 補(bǔ)碼不僅解決了[-0]的問題,更核心的是讓計(jì)算機(jī)做減法運(yùn)算,變成加法運(yùn)算。A - B = A + B的補(bǔ)碼
- 使用補(bǔ)碼,將減法變成加法運(yùn)算,這樣硬件上只需有加法器即可,不需要其他硬件,降低了電路的復(fù)雜度
- 使用補(bǔ)碼,不浪費(fèi)編碼個(gè)數(shù),存儲(chǔ)空間利用率高
- 補(bǔ)碼可以用n&0判斷負(fù)數(shù)奇偶
- 所以計(jì)算機(jī)底層存儲(chǔ)數(shù)據(jù)時(shí)使用的是二進(jìn)制數(shù)字,但是計(jì)算機(jī)在存儲(chǔ)一個(gè)數(shù)字時(shí)并不是直接存儲(chǔ)該數(shù)字對(duì)應(yīng)的二進(jìn)制數(shù)字,而是存儲(chǔ)該數(shù)字對(duì)應(yīng)二進(jìn)制數(shù)字的補(bǔ)碼
定點(diǎn)數(shù)和浮點(diǎn)數(shù)
定點(diǎn)數(shù)
定點(diǎn)數(shù)的意思是:即約定機(jī)器中所有數(shù)據(jù)的小數(shù)點(diǎn)位置是固定不變的。通常將定點(diǎn)數(shù)據(jù)表示成純小數(shù)或純整數(shù),為了將數(shù)表示成純小數(shù),通常把小數(shù)點(diǎn)固定在數(shù)值部分的最高位之前;而為了將數(shù)表示成純整數(shù),則把小數(shù)點(diǎn)固定在數(shù)值部分的最后面。例如:十進(jìn)制的 25.125
- 整數(shù)部分:25使用二進(jìn)制表示為:11001
- 小數(shù)部分:0.125使用二進(jìn)制表示為:.001
- 所以合起來(lái)使用11001.001 表示十進(jìn)制的25.125
本文的原碼、反碼、補(bǔ)碼概念都是基于定點(diǎn)數(shù)
浮點(diǎn)數(shù)
定點(diǎn)數(shù)表示法的缺點(diǎn)在于其形式過(guò)于僵硬,固定的小數(shù)點(diǎn)位置決定了固定位數(shù)的整數(shù)部分和小數(shù)部分,不利于同時(shí)表達(dá)特別大或特別小的數(shù),最終,絕大多數(shù)現(xiàn)代的計(jì)算機(jī)系統(tǒng)采納了浮點(diǎn)數(shù)表達(dá)方式,這種表達(dá)方式利用科學(xué)計(jì)數(shù)法來(lái)表達(dá)實(shí)數(shù),即用一個(gè)尾數(shù)(Mantissa,尾數(shù)有時(shí)也稱為有效數(shù)字,它實(shí)際上是有效數(shù)字的非正式說(shuō)法),一個(gè)基數(shù)(Base),一個(gè)指數(shù)(Exponent)以及一個(gè)表示正負(fù)的符號(hào)來(lái)表達(dá)實(shí)數(shù) 例如:
- 352.47 = 3.5247 * 10的2次方
- 178.125轉(zhuǎn)化為二進(jìn)制為 10110010.001,又可表示為:1.0110010001 乘以 2的111次方(111是7的二進(jìn)制表示)
- 123.45用十進(jìn)制科學(xué)計(jì)數(shù)法可以表示為1.2345x10的2次方,其中1.2345為尾數(shù),10為基數(shù),2為指數(shù)。浮點(diǎn)數(shù)利用指數(shù)達(dá)到了浮動(dòng)小數(shù)點(diǎn)的效果,從而可以靈活地表達(dá)更大范圍的實(shí)數(shù)。
字符串編碼
ASCII 碼
在計(jì)算機(jī)中, 不僅數(shù)值可以用二進(jìn)制表示,字符串也能用二進(jìn)制表示。上世紀(jì)美國(guó)制定了一套字符編碼,對(duì)英語(yǔ)字符與二進(jìn)制位之間的關(guān)系,加上數(shù)字和一些特殊符號(hào), 然后用 8 位的二進(jìn)制,就能表示我們?nèi)粘P枰乃凶址?,這個(gè)就是我們常常說(shuō)的ASCII 碼
ASCII 碼就好比一個(gè)字典,將二進(jìn)制和字符一一對(duì)應(yīng)。其中我們看幾個(gè)典型的例子:
- 小寫字母 a? 在 ASCII 里面,十進(jìn)制97,也就是二進(jìn)制的 0 110 0001,而大寫字母 A,十進(jìn)制65,對(duì)應(yīng)的二進(jìn)制 0 100 0001
- 需要注意的是,里面的數(shù)字,比如數(shù)字1,二進(jìn)制對(duì)應(yīng)0000 0001 在ASCII 里面,表示的其實(shí)是字符"1",對(duì)應(yīng)的二進(jìn)制是0 011 0001
- 字符串 15 也不是用0000 1111 這 8 位二進(jìn)制來(lái)表示,而是變成兩個(gè)字符 1 和 5 連續(xù)放在一起,也就是0 011 0001和 0 011 0101,需要用兩個(gè) 8 位二進(jìn)制來(lái)表示 。所以計(jì)算機(jī)儲(chǔ)存數(shù)據(jù)時(shí),二進(jìn)制序列化會(huì)比直接存儲(chǔ)文本能節(jié)省大量空間
EASCII:擴(kuò)展的 ASCII
一開始美國(guó)編寫ASCII表,英語(yǔ)用128個(gè)符號(hào)編碼就夠了,但隨著計(jì)算機(jī)的普及,西歐國(guó)家不全是英語(yǔ)國(guó)家,有德語(yǔ),法語(yǔ)等等
比如 字母上方有注音符號(hào),它就無(wú)法用 ASCII 碼表示。于是歐洲工程師就決定,利用字節(jié)中閑置的最高位編入新的符號(hào)。他們把 ASCII 擴(kuò)充變成了 EASCII,這擴(kuò)充的包括希臘字母、特殊的拉丁符號(hào)等。由于 ASCII 只占了 7 位,所以 EASCII 把第 8 位利用起來(lái),仍然是一個(gè)字節(jié)來(lái)表示,這時(shí)表示的字符個(gè)數(shù)是 256。
Unicode
但 EASCII 并沒有成功,西歐國(guó)家以及各個(gè) PC 廠商各自定義出了好多不同的編碼字符集,ISO-8859將西歐國(guó)家的編碼一起包含進(jìn)去。但隨著計(jì)算機(jī)來(lái)到中國(guó),那些歐美國(guó)家把 現(xiàn)有的字典都用完,而且漢字有十多萬(wàn)個(gè),所以急需新的"字典"。GB2312編碼就出來(lái)了,使用兩個(gè)字節(jié)表示一個(gè)漢字(漢字太多),所以理論上最多可以表示 256 x 256 = 65536 個(gè)符號(hào)。后來(lái)GBK編碼 將古漢字等生僻字加進(jìn)來(lái)。臺(tái)灣地區(qū)又創(chuàng)造了BIG5編碼,再后來(lái)GB18030對(duì)東南亞地區(qū)的文字,進(jìn)行了統(tǒng)一。簡(jiǎn)單了解下這些編碼,就不具體展開了
再后來(lái)計(jì)算機(jī)全球普及,各個(gè)國(guó)家地區(qū)的文字編碼太多太亂,Unicode編碼的出現(xiàn),為了統(tǒng)一全世界的所有字符。Unicode 是一個(gè)很大的集合,現(xiàn)在的規(guī)模可以容納100多萬(wàn)個(gè)符號(hào)。
由于Unicode 只是一個(gè)字符集(Charset),它只規(guī)定了符號(hào)的二進(jìn)制代碼,卻沒有規(guī)定這個(gè)二進(jìn)制代碼應(yīng)該如何存儲(chǔ),也就是字符編碼(Character Encoding),這就導(dǎo)致計(jì)算機(jī)無(wú)法區(qū)別 Unicode 和 ASCII ,比如三個(gè)字節(jié)表示一個(gè)符號(hào),而不是分別表示三個(gè)符號(hào)呢?
隨著互聯(lián)網(wǎng)的崛起,UTF-8 就是在互聯(lián)網(wǎng)上使用最廣的一種 Unicode 的實(shí)現(xiàn)方式。UTF-8 它是一種變長(zhǎng)的編碼方式。它可以使用1~4個(gè)字節(jié)表示一個(gè)符號(hào),根據(jù)不同的符號(hào)而變化字節(jié)長(zhǎng)度。Unicode 字符集中的大部分漢字,如果用 UTF-8 編碼的話,是占 3 個(gè)字節(jié)的。
下面我們看看UTF-8是如何兼容Unicode的:UTF-8編碼致力于統(tǒng)一世界上所有的字符集,所以它的設(shè)計(jì)上既向下兼容ASCII碼的編碼方式,同時(shí)又考慮了可拓展性,規(guī)則如下:1)對(duì)于單字節(jié)的符號(hào):字節(jié)的第一位設(shè)為0,后面7位為這個(gè)符號(hào)的 Unicode 碼。與 ASCII 編碼規(guī)則相同;2)對(duì)于n字節(jié)的符號(hào)(n > 1):第一個(gè)字節(jié)的前n位都設(shè)為1,第n + 1位設(shè)為0,后面字節(jié)的前兩位一律設(shè)為10。剩下的沒有提及的二進(jìn)制位,全部為這個(gè)符號(hào)的 Unicode 碼。
Unicode | UTF-8 | byte 數(shù) |
0000~007F | 0XXX XXXX | 1 |
0080~07FF | 110X XXXX 10XX XXXX | 2 |
0800~FFFF | 1110 XXXX 10XX XXXX 10XX XXXX | 3 |
1 0000~1F FFFF | 1111 0XXX 10XX XXXX 10XX XXXX 10XX XXXX | 4 |
我們可以發(fā)現(xiàn),UTF-8 編碼的第一位如果是 0,則只有一個(gè)字節(jié),跟 ASCII 編碼完全一樣,所以兼容了。如果是 110 開頭,則是兩個(gè)字節(jié),以此類推如上表所示。所以開頭幾位的值,是編碼本身,同時(shí)又是判斷后續(xù)還有幾個(gè)字節(jié)數(shù)的推碼(通過(guò)推碼才能判斷這個(gè)字節(jié)之后還有幾個(gè)字節(jié)共同參與一個(gè)字符的表示)
亂碼的來(lái)源
編碼是把數(shù)據(jù)從一種形式轉(zhuǎn)換為另外一種形式的過(guò)程,而解碼則是編碼的逆向過(guò)程。編碼是一種格式,解碼是另一種格式,當(dāng)然會(huì)出問題。下面我們舉個(gè)例子,來(lái)看看這個(gè)問題:
- 創(chuàng)建hello.txt文件,用Notepad++打開編輯,以 UTF-8 格式寫入你好
- 然后我們改變Notepad++的formaat格式,改為GB2312,然后你好就變成了浣犲ソ
在UTF-8 字典中,你好?兩個(gè)字的16進(jìn)制編碼分別是E4BDA0、E5A5BD?在GB2312字典中,浣犲ソ?三個(gè)字的16進(jìn)制編碼分別是 E4BD、A0E5、A5BD
由于在UTF-8 編碼漢字是 3 個(gè)字節(jié),在GB2312編碼漢字卻是2個(gè)字節(jié),計(jì)算機(jī)用GB2312去解析UTF-8,硬生生的把3個(gè)字節(jié)以每2個(gè)字節(jié)為一組去解碼,所以才會(huì)有出現(xiàn)這種亂碼。當(dāng)我們知道亂碼出現(xiàn)的原因,如何解決就變的非常簡(jiǎn)單了
參考資料:
《編碼:隱匿在計(jì)算機(jī)軟硬件背后的語(yǔ)言》
《深入理解計(jì)算機(jī)系統(tǒng) 第三版》
《計(jì)算機(jī)組成原理》
《深入計(jì)算機(jī)組成原理》
https://www.ruanyifeng.com/blog/2007/10/ascii_unicode_and_utf-8.html
https://www.zhihu.com/question/20159860
https://blog.csdn.net/f919976711/article/details/116714860
本文轉(zhuǎn)載自微信公眾號(hào)「 小牛呼嚕嚕」,作者「小牛呼嚕嚕」,可以通過(guò)以下二維碼關(guān)注。
轉(zhuǎn)載本文請(qǐng)聯(lián)系「小牛呼嚕?!构娞?hào)。