[TOC]
>[ 為什么計算機能讀懂 1 和 0 ?](https://www.zhihu.com/question/20112194)
# 位,字節,字長
**位**:bit 最小單元 又叫比特數.
在數字世界里沒有電影、沒有雜志、沒有一首首的樂曲,只有一個個的數字“1”和“0”。以前人們對于數字世界中的這兩個數字還不知道如何命名,直到現1946年普林斯頓大學的統計學家約翰.土吉(john turkey)把它定為進制,才有了比特(Bit)這一術語。比特是電腦當中最小的單位。
**字節**:byte 機器語言的單位, 計算機中可單獨處理的最小單位。
**字長**是ALU(算術邏輯部件)在一個時鐘周期內最多能運算的二進制位數。
## 換算
另外,Byte通常簡寫為B(大寫),而bit通常簡寫為b(小寫)。可以這么記憶,大寫的為大單位,實際數值小,小寫的為小單位,實際數值較大,1B=8b。
B=字節 KB=千字節 MB=兆字節 GB=千兆字節
由于計算機內部采用萬能的二進制,而2的10次方1024又非常接近1000,于是很自然的就采用了1k=1024這種換算方式,非常方便。
~~~
1 Byte = 8 Bits
1 KB = 1024 Bytes
1 MB = 1024 KB
1 GB = 1024 MB
~~~
可是硬盤廠商在描述自己產品容量時確沒有采用這一方式,而是傳統的1000進制,于是問題出現了。一塊標稱100GB的硬盤是100,000,000,000字節,換算成計算機內部的表示方法就只有93GB左右了,格式化后會更少一點。
~~~
1KB=1000B
1MB=1000KB
1GB=1000MB
~~~
為了避免兩種不同的換算方式帶給消費者的困惑,Mac OS X和Linux開始陸續采用1000進制顯示硬盤容量(注意是顯示,也就是給人看的,實際上這個東西怎么換算和操作系統底層的使用一點關系都沒有,如@pansz 提到的),這樣消費者就可以在系統中看到和標稱容量差不多一樣大小的硬盤了。
這就造成了硬盤標稱的容量和操作系統中顯示的實際容量不同。
## 位
“字”由若干個字節構成,字的位數叫做字長,字長就是說字所對應的二進制數的長度。不同的機器有不同的字長。
例如一臺8位機,它的1個字就等于1個字節,字長為8位。
如果是一臺16位機,那么,它的1個字就由2個字節構成,字長為16位。
前期的DOS就是8位的,后期的DOS是16位的,Win9X是基于DOS的,所以也是16位的,NT核心的Windows是32位的,現在也有了64位的XP/2003,CPU也有了64位的,這個操作系統和CPU所說的位就是bit的意思,即二進制數的長度。
字節是固定由8位二進制構成,Byte 字節,由八個二進制位組成,是計算機中表示存儲空間的最基本容量單位。
64位系統就代表了64位的二進制代表一個字,換算成字節就是64/8=8,即是說由8字節構成一個字,32位系統就是32/8=4,4個字節代表一個字。
在計算機中,數據只用0和1兩種表現形式,(這里只表示一個數據點,不是數字),一個0或者1占一個“位”,
而系統中規定8個“位”為一個“字節”,用來表示常用的256個字母、符號、控制標記。
在64位計算機中,“一個字長”所占的字節數為8。
字長的字節數 = 計算機位數/8。單位 是“比特”,也就是“位”(bit,簡稱b),它表示 1個二進制位。
比“位”大的單位是“字節”(byte,簡稱B),它等于 8個二進制位。
## 字長
**平常我們說的32位機,64位機,說的就是32字長,64字長,英文叫word size**
字長越大,CPU運算能力越牛逼:
~~~
4位
8位
16位
32位
64位,現在大部分CPU都這個水平
~~~
字長:CPU一次操作可以處理的二進制位數(0或1), 1位= 1 bit
舉例子:
一個字長是8的cpu,一次能進行不大于`1111,1111` (8位) 的運算
一個字長是16的cpu ,一次能進行不大于 `1111,1111,1111,1111`(16位)的運算
## 字符,字符集,字符編碼
1. 字符:是各種文字和符號的總稱,包括各個國家的文字,標點符號,圖形符號,數字等。
3. 字符集:字符集是多個符號的集合,每個字符集包含的字符個數不同。
4. 字符編碼:字符集只是規定了有哪些字符,而最終決定采用哪些字符,每一個字符用多少字節表示等問題,則是由編碼來決定的。計算機要準確的處理各種字符集文字,需要進行字符編碼,以便計算機能夠識別和存儲各種文字
## 常見字符集的編碼:
常見的字符集有: **ASCII 字符集**, **GB2312 字符集**, BIG5 字符集, GB18030 字符集,**Unicode 字符集**,下面一一介紹:
### ASCII 字符集:
* 定義:
**美國信息互換標準代碼,是基于羅馬字母表的一套電腦編碼系統,主要顯示
英語和一些西歐語言,是現今最通用的單字節編碼系統。**
* 包含內容:
控制字符(回車鍵,退格,換行鍵等)
可顯示字符(英文大小寫,阿拉伯數字,西文符號)
擴展字符集(表格符號,計算符號,希臘字母,拉丁符號)
* 編碼方式:
第 0-31 號及 127 號是控制字符或通訊專用字符;
第 32-126 號是字符,其中 48-57 號為 0-9 十個阿拉伯數字, 65-90 號為 26 個大寫英文字母, 97-122 號為 26 個英文小寫字母,其余為一些標點符號,運算符號等。
**在計算機存儲單元中,一個 ASCII 碼值占一個字節( 8 個二進制位),最高位是用作奇偶檢驗位。**【奇偶校驗是指:在代碼傳送的過程中,用來檢驗是否出錯的一種方法。】奇偶校驗分為奇校驗和偶校驗。
信息是以比特流的方式傳輸的,類似01000001。在傳輸過程中,有可能會發生錯誤.
比如,我們存儲了01000001,但是取出來卻是01000000,即低位由0變成了1。為了檢測到這種錯誤,我們可以通過“奇偶校驗”來實現。
假如,我們存儲的數據是一個字節,8個比特位,那我們就可以計算每個字節比特位是1的個數,如果是偶數個1,那么,我們就把第九個位設為1,如果是奇數個1,那么就把第九個位設為0,這樣連續9個字節比特位為1的位數肯定是奇數。這中方法叫做“奇校驗”,“偶校驗”和此類似。當然,在實際應用中,也可以把一個字節的前7位作為數據位,最后一個為作為校驗位。
~~~
奇校驗規定:正確的代碼一個字節中 1 的個數必須是奇數,若非奇數,則在最高位添 1;
偶校驗規定:正確的代碼一個字節中 1 的個數必須是偶數,若非偶數,則在最高位添1。
~~~
**校驗方法**
奇校驗:就是讓原有數據序列中(包括你要加上的一位)1的個數為奇數
`1000110(0)`你必須添0這樣原來有3個1已經是奇數了所以你添上0之后1的個數還是奇數個。
偶校驗:就是讓原有數據序列中(包括你要加上的一位)1的個數為偶數
`1000110(1)`你就必須加1了這樣原來有3個1要想1的個數為偶數就只能添1了。[1]
### GB2312 字符集:
* 定義:
信息交換用漢字編碼字符集。是中國標準的簡體中文字符集,它所收錄的漢字已經覆蓋 99.75%的使用頻率,在中國大陸和新加坡廣泛使用。
* 包含內容:
GB2312 收錄了簡化漢字及一般字符,序號,數字,拉丁字母,日文假名,希臘字母,俄文字母,漢語拼音符號,漢語注音字母,共 7445 個圖形字符。
其中包括 6763 個漢字,一級漢字 3755 個,二級漢字 3008 個。
* 編碼方式:
GB2312 對所收漢字進行了“分區”處理,每區含有 94 個漢字或者符號,這種表示方法也叫做“區位碼”。
它是用雙字節表示的,前面的字節為第一字節,又稱“高字節”,后面的為第二字節,“低字節”。高位字節,把 01-87 區的區號加上 0xA0 (相當于數字 160);低位字節把 01-94區的區號加上 0xA0(相當于數字 160)。
舉個簡單的小例子:第一個漢字——“啊”,它的區號為 16,位號 01,則區位碼是 1601。則高字節位:16+0xA0=0xB0;低字節位: 01+0xA0=0xA1,所以“啊”的漢字處理編碼為0xB0A1。
### GBK 字符集:
* 定義:
GBK 是 GB2312 字符集的擴展( K) (中國的中文編碼表升級,融合了更多的中文文字符號。 ),它收錄了 21886 個符號,它分為漢字區和圖形符號區,漢字區包括 21003 個字符。** GBK 字符集主要擴展了繁體中文字的支持。**
### BIG5 字符集:
* 定義:
又稱大五碼,由臺灣五家軟件公司創立。因為當時臺灣沒有一個標準的字符集,而且 GB2312 又沒有收錄繁體字,所以才推出了 BIG5。
* 包含內容:
BIG5 字符集共收錄了 13053 個中文字,該字符集在臺灣使用。但是沒有考慮
到社會上流通的人名,地方用字,方言用字,化學及生物科等用字,沒有包
含日文平假名及片假字母。
* 編碼方式:
BIG5 也采用雙字節存儲方法,一兩個字節編碼一個字。高位字節的編碼范圍
是 0xA1-0xF9,低位字節的編碼范圍是 0xA1-0xFE。
### GB18030 字符集:
* 定義:
GB18030 字符集標準解決漢字,日文假名,朝鮮語和中國少數民族文字組成的大字符集計算機編碼問題。
* 包含內容:
該標準的字符總編碼空間超過 150 萬個編碼位,收錄了 27484 個漢字,覆蓋中文,日文,朝鮮語和中國少數民族文字。滿足中國大陸,香港,臺灣,日本和韓國等東南亞地區信息交換多文種,大字量,多用途,統一編碼格式的要求。
* 編碼方式:
GB8030 標準采用單字節,雙字節和四字節三種方式對字符編碼。 單字節部分使用 0x00-0x7F 碼(對應于 ASCII 碼的相應碼);
雙字節部分,首字節碼從 0x81-0xFE,尾字節碼分別是 0x40-0x7E 和 0x80-0xFE。
四字節部分采用 0x30-0x39 作為雙字節編碼擴充的后綴,這樣擴充的四字節編碼,其范圍是 0x81308130-0x0xFE39FE39,其中第一,三個字節編碼位均為0x81-0xFE,第二,四個為 0x30-0x39。
### ISO8859-1:
拉丁碼表。歐洲碼表
用一個字節的 8 位表示。
### Unicode 字符集:
* 定義:
( 國際標準碼,融合了多種文字。 所有文字都用兩個字節來表示,**Java 語言使用的就是 unicode**) University multiple-object coded character set(通用多八位編碼字符集),支持世界上超過 650 種語言的國際字符。 Unicode 允許在同一服務器上混合使用不同語言,它為每種語言的每個字符設定了統一并且唯一的二進制編碼,以滿足跨平臺,跨語言進行文本轉換,處理的要求。
* 編碼方式:
Unicode 標準始終使用十六進制數字,固定使用 2 個字節來表示一個字符,
共可以表示 65536 個字符。而且書寫時在前面加上前綴“ U+”,例如 A 的編
碼是 004116,則書寫成“ U+0041”。
* Unicode 字符集包含的編碼方案:
**UTF-8**:( 最多用三個字節來表示一個字符。)
UTF8 是 unicode 其中的一個使用方式。
UTF 的意思是:unicode translation format,即把 unicode 轉作某種格式的意思。 UTF-8使用可變長度字節來存儲 unicode 字符,如 ASCII 字母還是采用一個字符來存儲,希臘字母等采用 2 個字符來存儲,而常用的漢字要使用 3 字節,輔助平面字符則使用 4 字節。
**UTF-16**:
使用一個或兩個未分配的 16 位代碼單元的序列對 unicode 代碼
點進行編碼,即 2 個字節表示一個字符。
**UTF-32**:
將每一個 unicode 代碼點表示為相同值的 32 位整數。
**關于 unicode 編碼的一個問題:**
使用記事本另存為時,可 以 在 ANSI , GBK,Unicode ,unicode big endian 和 UTF-8 這幾種編碼之間相互轉換。同樣是 txt 文
件, windows 是怎么識別編碼的呢?
答:平時注意的話可以發現 Unicode, unicode big endian 和 UTF-8編碼的 txt 文件的開頭會多出幾個字節,分別是(FF,FE),( FE,FF),( EF,BB,BF)。那么這些標記都是基于什么標準呢?ANSI 字符集: ASCII 字符集,以及由此派生并兼容的字符集。
### UTF-16 與 UTF-8:
如“連通”兩個字,在 UTF-16 中為:`DE 8F 1A 90`,兩個字節決定一個漢字;在 UTF-8 中則為: E8 BF 9E E9 80 9A,即 3個字節決定一個字符。
當一個軟件打開一個文本時,首先是要決定這個文本究竟是使用哪種字符集的哪種編碼保存的,軟件一般采用三種方式來決定文本的字符集和編碼:檢測文件頭標識,提示用戶選擇,根據一定的規則猜測。
*不同編碼方式的開頭字節如下:*
| 開頭字節 | 字符集的編碼 |
| --- | --- |
| EF BB BF | UTF-8 |
| FF FE | UTF-16, little endian |
| FE FF | UTF-16, big endian |
|FF FE 00 00 | UTF-32, little endian|
| 00 00 FE FF | UTF-32, big endian |
注: endian(字節存儲次序) 是指字節序, big endian(大尾)和 little endian(小尾)是 CPU 處理多字節數的不同方式。例如“漢”的 unicode 編碼是 6C49,寫到文件中,如果將 6C 寫在前面就是 big endian,將 49寫在前面就是 little endian。
### 總結
從 ASCII, GB2312, GBK 到 GB18030,這些編碼方法是向下兼容的,即同一個字符在這些方案中總是有相同的編碼,后面的標準支持更多的字符。在這些編碼中,英文和中文可以統一的處理。**區分中文編碼的方法是高字節的最高位不為0。**
計算機使用的缺省編碼方式就是計算機的內碼。有的中文 windows 的缺省內碼還是 GBK,可以通過 GB18030 升級包升級到 GB1030。不過相對 GBK 新增的字符,普通人很難用到的,通常我們用 GBK 來指代中文 windows 內碼。
GB2312 的原文是區位碼,從區位碼到內碼,需要在高字節和低字節上分別加上 A0。