公廁里的二進(jìn)制究竟寫的什么
hello,大家春節(jié)好啊,我是小樓。
春節(jié)帶娃逛公園,在公園廁所里發(fā)現(xiàn)了一張有意思的圖:
好幾種語言寫的 “往前一小步,文明一大步”,男同胞應(yīng)該大部分都看過類似的標(biāo)語,但這個(gè)二進(jìn)制有點(diǎn)意思。
我把這個(gè)圖發(fā)給一個(gè)公務(wù)員朋友,他說這個(gè)只有你們程序員看得懂,我說我也看不懂。
原來在外行眼里,程序員竟然還能看懂二進(jìn)制~
回到家后,我在想,這二進(jìn)制究竟寫的啥?難道設(shè)計(jì)者是程序員?又或許是設(shè)計(jì)者瞎寫的?
為了看懂這段二進(jìn)制,得先想辦法把這段01組成的文本搞出來。
靠肉眼加手敲顯然不行,我想到了微信自帶的識別文字:
顯然不對,丟了很多。
接著我想到了 OCR,但是搜了一下發(fā)現(xiàn)全是接口文檔的廣告,還需要自己實(shí)現(xiàn),顯然不可能為了識別一張圖片去開發(fā)個(gè)程序,于是又繼續(xù)搜如何提取圖片文字,發(fā)現(xiàn)了一款微信小程序,試了下,還真就識別出來了
11100101100100001001000111100101100010011000110111100100101110001000000011100101101100001000111111100110101011011010010100100000111001101001011010000111111001101001100010001110111001001011100010000000111001011010010010100111
111001101010110110100101
看了下,248個(gè)0和1的組合,248比較特殊,可以被8整除,斗膽猜測是 ASCII 碼,每8位表示一個(gè),于是我簡單寫了個(gè)Go程序驗(yàn)證下:
func TestBinary(t *testing.T) {
str := "11100101100100001001000111100101100010011000110111100100101110001000000011100101101100001000111111100110101011011010010100100000111001101001011010000111111001101001100010001110111001001011100010000000111001011010010010100111111001101010110110100101"
for i := 0; i < len(str); i = i + 8 {
code, _ := strconv.ParseInt(str[i:i+8], 2, 64)
fmt.Printf("%c", int(code))
}
}
結(jié)果一運(yùn)行出現(xiàn)了:
這是啥玩意?難道是我代碼寫錯(cuò)了?
于是我想直接問一下百度,這串二進(jìn)制如何轉(zhuǎn)換為ASCII碼
百度丟給我一段 python 代碼,雖然我對 py 不太熟,但還是知道怎么運(yùn)行,于是我把它粘貼到文件里,保存為 test.py 文件,然后執(zhí)行 python test.py
AI 還真是厲害!
原來這里是對中文的編碼,我一直以為是英文。這里應(yīng)該是 unicode 編碼,通常用 UTF-8 來存儲 unicode 字符,它是一種變長的存儲方式,比較節(jié)省空間,使用1~4個(gè)字節(jié)表示字符,漢字通常是3~4個(gè)字節(jié)。
那么問題來了,給一串二進(jìn)制怎么知道字符使用了幾個(gè)字節(jié)表示呢?其實(shí)是有個(gè)規(guī)定:
- 1字節(jié):0xxx xxxx
- 2字節(jié):110x xxxx 10xx xxxx
- 3字節(jié):1110 xxxx 10xx xxxx 10xx xxxx
- 4字節(jié):1111 0xxx 10xx xxxx 10xx xxxx 10xx xxxx
用上面的二進(jìn)制舉例,可以把第一個(gè)漢字撈出來:
1110 0101 1001 0000 1001 0001
對應(yīng)上面規(guī)則為3字節(jié),再把固定的前綴去掉,得到unicode編碼:
0101 0100 0001 0001
轉(zhuǎn)換為16進(jìn)制:\u5411,查詢下果然是“向”
同理可得其他字符。按照這個(gè)邏輯來寫代碼解析就比較簡單了,但 python 的 chr 函數(shù)還是有點(diǎn)意思,為什么這么說呢?因?yàn)樗皇前凑瘴覀冞@個(gè)邏輯去解析的,它是固定8位8位地解析,結(jié)果也能解析完整。如果把每次調(diào)用 chr 的結(jié)果都輸出,你就會發(fā)現(xiàn)它的厲害之處:
好了 python 這個(gè)彩蛋留給大家去探索,本文到此為止,我們下期再見~
