oeasy教您玩轉python - 008 - # ascii碼錶

 

ASCII 碼錶

回憶上次內容

  • 通過 help()可以從 python 命令行模式進入到幫助模式

    • 通過 q 退出
  • ord(c)和 chr(i)

    • 這是倆函數
    • 這倆是一對,相反相成的

      • ord 通過字符找到對應的數字
      • chr 通過數字找到對應的字符
    • 字符的本質是數字
  • Python 裏面的字符對應着一些數字

    • a對應 97
    • b對應 98
    • c對應 99
  • 可是,爲什麼是這樣的對應關係,誰規定的,必須的麼?🤔

小寫字母

#輸出a,b,c
ord("a")
ord("b")
ord("c")
#輸出z-a的數字差距,相對序號
ord("z")-ord("a")
#輸出a的相對序號
ord("a")-ord("a")
  • a、b、c 這些字符是挨着的
  • 正好從0到25,總共26個數字🔢
  • 對應數字也是挨着的

編碼規律

  • 從 a-z 應該都是挨着的
  • 26 個英文字母之間,數值差距是 25,說明都是挨着的
  • 爲什麼是從 97 開始?

    • 應該還有別的字符
    • 除了小寫字母之外、大寫字母、數字、符號他們都是如何的分佈的呢?
    • 我想把所有 ASCII 字符 0-127 全都打出來
    • 可以麼?

遍歷範圍

for i in range(0,128):
    print(i,end=",")
  • 我們先把0-127 挨牌兒捋一遍

  • 然後如何找到數字對應的字符呢?

對應字符

  • 通過數字找到對應的字符是chr

for i in range(0,128):
    print(hex(i),chr(i),sep=":",end="    ")
  • print(hex(i),chr(i),sep=":",end=" ")

    • hex(i)

      • 輸出i的十六進制狀態
    • chr(i)

      • 輸出i的字符狀態
    • sep=':'

      • 分隔符爲冒號
    • end=" "

      • 結束時輸出3個空格
  • 結果如何呢?

結果

  • 這不是很整齊啊
  • 爲什麼在 0xa-0xc 好像換行很突然
  • 後面可以看到字符和序號一一對應的關係
  • 不過不是很明確
  • 有什麼方式可以看起來更明確麼?

安裝 ASCII

sudo apt install ascii
  • Dec 對應的是 10 進制數
  • Hex 對應的是 16 進制數
  • 後面的是具體字符
  • 字符包括

    • 控制
    • 符號
    • 英文大小寫字母
  • 這樣就把各種字符和一個二進制數字對應起來了

  • 這個 ASCII 什麼時候開始有的呢?

ASCII 碼錶

  • 1967 年的時候就有了最初這個 ASCII 碼錶🔡

    • 當時計算機用高電平和低電平分別表示 0 和 1

      • 實際上計算機中所有的數據都是 0 和 1
    • 這建立起了 字符二進制數映射關係
  • 字符二進制數映射關係 如果不一致

    • 面對同一個二進制數 01010101
    • 就會映射到不同的字符
    • 人們看到不同的字符就認爲是亂碼
  • 當時美國的工程師定義了一套編碼規則

    • ASCII

      • American Standard Code for Information Interchange
    • 美國信息交換標準代碼

由來

  • 這標準是美國信息交換標準代碼是由美國國家標準學會制定的

    • (American National Standard Institute , ANSI )
    • 最初是美國標準
  • 後來是國際標準化組織定爲國際標準

    • (International Organization for Standardization, ISO)
    • 稱爲 ISO 646 標準
  • 最後一次更新則是在 1986 年

    • 到目前爲止共定義了 128 個字符

解碼 ASCII

  • 我們找到小寫的a

    • 先向上找到110

      • 這是他的765
      • 高三位
    • 再向左找到0001

      • 這是他的4321
      • 第四位
    • 在前面加一個0
    • 得到(01100001)2進制
    • 對應着(97)10進制數
    • 也就是(0x61)16進制數
    • 剛好對應一個字節

對應關係

  • 1 個 字節 byte

    • 正好 8 個 bit 位
    • 相當於 2 位 16 進制數
    • 16 進制數 更容易讀出
  • 十六進制數很適合輸出字節狀態
  • 聽起來找到了字符和字節狀態之間的映射對應關係
  • 我們能在遊樂場上驗證一下嗎?

遊樂場

  • 進入 python3 幫助模式
  • 我們可以查詢 hex

    • hex 對應 hexadicimal 十六進制
  • help(hex)

動手

#得到a的序號
ord("a")
#輸出97對應的16進制形式
hex(97)
#找到a對應的16進制形式數字對應的字符
hex(ord("a"))
  • 0x61就是十六進制的61

    • 0x是十六進制的前綴標誌

  • 可是爲什麼 16 進制使用 0x 作爲前綴?

0x 前綴

  • x 的起源

    • 0x 的 x 是取自 hex 的 x

  • 0 的起源

    • 變量名開頭不許是數字
    • 0 開頭肯定是數字
    • 但正常情況下寫數字不會用 0 開頭
    • 這保證 0 開頭很容易和 10 進制區分開
    • 在 C 語言之前的 B 語言用 0 開頭表示 8 進制

      • C 語言繼承了類似設定

        • 0 開頭表示數字
        • 0x 開頭表示 16 進制數
  • python 也繼續繼承

    • 字符對應着數字
    • 數字也可以轉化爲字符
    • 字符和二進制數之間的關係其實是

      • 編碼 encode
      • 解碼 decode

編碼解碼

  • 編碼

    • 就是用預先規定的方法將文字、數字、其它對象編成數碼
    • 將信息、數據轉換成規定的電脈衝信號
    • 簡單來說就是給大白菜編個號

  • 解碼是編碼的逆過程

    • 用特定方法,把數碼還原成它所代表的內容
    • 將電脈衝信號、光信號、無線電波等轉換成它所代表的信息、數據等的過程
    • 簡單說就是掃條碼知道這個是一個大白菜並知道價格等

  • 我們用python試試編碼解碼

encode和decode

  • str(字符串)'a' encode(編碼)之後 爲 bytes(字節序列) b'\x61'

  • bytes(字節序列)b'\x61' decode(解碼)之後爲 爲 str(字符串)'a'
  • 編碼(encode) 和解碼(decode) 互爲逆運算
  • 很像

    • 字符(chr)和 序號(ord)

編碼解碼

  • 可以先編碼再解碼
  • 也可以先解碼再編碼
  • 繞來繞去
  • 也沒做神馬😁

  • 掌握這個基礎是最起碼
  • 基本功要練得硬橋硬馬
  • 實戰方能穩紮穩打
  • 否則以後各種亂碼

  • 字節除了用十六進制顯示之外
  • 還可以用二進制顯示麼?

bin(number)

  • 這次我們來試試把數字轉化爲二進制形式
  • 查詢 bin

    • bin 對應 binary 二進制

動手

#得到a的序號
ord("a")
#輸出97對應的16進制形式
bin(97)
#找到a對應的十六進制形式
bin(ord("a"))
  • 0b1100001是二進制數1100001
  • 0b是 2 進制數的前綴標誌

    • 正如0x是 16 進制數的前綴標誌

和 ASCII 表對比

  • 驗證成功
  • 這充分證明了我們用的確實是 ASCII 表!!!👏👏
  • 廢話!🦧
  • 我們會用 hex、bin 把 10 進制數轉化爲八進制、二進制形式
  • 能把其他進制轉化回十進制麼?

其他進制 轉化爲回 10進制 int(number)

  • 用的是 int

  • 這個 int 什麼來歷?
  • 我們 help()裏面去找找

大小字母差值

  • 0x41-0x5A這個範圍是大寫字母
  • 0x61-0x7A這個範圍是小寫字母
#輸出a的ASCII嗎
ord("a")
#輸出A的ASCII嗎
ord("A")
#輸出大小寫之差
ord("a")-ord("A")
#差值的16進制形式
hex(ord("a")-ord("A"))
#差值的2進制形式
bin(ord("a")-ord("A"))
  • 大寫字母和小寫字母相差(32)10進制
  • 正好是(0x20)16進制

  • 爲什麼不多不少
  • 就差 0x20 呢?
  • 怎麼那麼寸呢?🤔

ASCII 碼錶趣事

  • 其實最初不是相差 0x20

    • 這個 0x20 正好是一個二進制位
    • 對應 b6 這個位
    • 之前 ibm 的 EBCDIC 編碼並不是這樣的
  • 那爲什麼要改成這樣子呢?
  • 有了這種對應關係之後

    • 做大小寫不敏感的字符串查找就快多了
    • 這個 0x20 發生在 1963 年 5 月

      • The X3.2.4 task group voted its approval for the change to ASCII at its May 1963 meeting.
      • Locating the lowercase letters in columns 6 and 7 caused the characters to differ in bit pattern from the upper case by a single bit, which simplified case-insensitive character matching and the construction of keyboards and printers.
    • 如果是大寫字母

      • 修改1位之後,都變成小寫字母
      • 然後直接查找就好了

ASCII 碼錶範圍

  • 0x41-0x5A這個範圍是大寫字母
  • 0x61-0x7A這個範圍是小寫字母
  • 0x30-0x39這個範圍是數字

    • 數字的編碼減去0x30正好得到數字本身

  • 我們再來看看 ASCII

ASCII

  • 0x20-0x7F之間有各種符號
  • 0x00-0x1F之間的東西是什麼?

    • 目前還不知道
    • 也許有一天可以進行進一步地探索

  • 可以肯定都是

    • 很多字符來自與更早之前的摩斯電碼

更早之前的摩斯電碼

  • ASCII 也不是從無到有的

    • 在 ASCII 之前就有摩斯電碼
    • 也是一種編碼方法
    • 《oeasy 教您玩轉電路基礎》第 18 話介紹過
  • 下圖是他的編碼表

    • 分成長和短兩種信號,就是嘀和嗒

摩斯電碼通信規則

  • 下圖是他的通信規則
  • 三個斷確認本字符結束了
  • 三個斷也就是字符之間的分隔符
  • 錄入狀態並不是 0、1 兩種狀態
  • 而是長、短、暫停三種狀態

  • 爲什麼這樣編碼呢?

效率問題

  • 編碼的規則是常用的字符點擊次數少

    • 按照字符出現概率分配對應點擊數量

      • TE 出現頻率最高
      • 所以用一次點擊電鍵的數量
    • 本質上是一棵霍夫曼樹

  • 當時完全由人進行發射和接收

    • 每個人發送數據的速度是不固定的
    • 每個人接收數據的速度取決於發送人的發送速度
    • 現查表是來不及的
    • 需要熟悉編碼表和常用縮寫
  • 這就是早期使用電來進行編碼的過程

    • 我們現在回到 ASCII 碼
  • 最後我們來總結一下

總結

  • 數制可以轉化

    • bin(n)可以把數字轉化爲 2進制
    • hex(n)可以把數字轉化爲 16進制
    • int(n)可以把數字轉化爲 10進制
  • 編碼和解碼可以轉化

    • encode 編碼
    • decode 解碼
  • ASCII 碼錶範圍

    • 0x41-0x5A 這個範圍是 寫字母
    • 0x61-0x7A 這個範圍是 寫字母
    • 0x30-0x39 這個範圍是 數字

      • 數字的編碼減去 0x30 正好得到數字本身
    • 0x20-0x7F之間有各種符號
    • 0x00-0x1F之間的東西是什麼?🤔
  • 我們下次再說
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章