0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學(xué)習在線(xiàn)課程
  • 觀(guān)看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區
會(huì )員中心
創(chuàng )作中心

完善資料讓更多小伙伴認識你,還能領(lǐng)取20積分哦,立即完善>

3天內不再提示

數據表示與編碼的奧秘:為什么8位數據范圍是-128到127?

嵌入式情報局 ? 來(lái)源:invalid s ? 2024-04-17 09:44 ? 次閱讀

很表面很淺薄的問(wèn)題。

簡(jiǎn)單說(shuō)愛(ài)怎么規定就怎么規定,甚至-1到254都行。無(wú)非是顯示時(shí)通過(guò)編碼表做個(gè)轉換的問(wèn)題而已。

不過(guò),當初選擇“補碼”這種編碼形式,卻并不像表面看起來(lái)那么淺薄。背后的道道可多著(zhù)呢。

首先,8位二進(jìn)制一共可以提供256個(gè)“碼點(diǎn)”;那么我們就總可以用這些“碼點(diǎn)”來(lái)編碼256種符號。

這種編碼方案有很多。最著(zhù)名的大概就是ASCII碼方案了,這個(gè)方案規定了英文字符(區分大小寫(xiě))、0~9這10個(gè)數字、標點(diǎn)符號以及一些控制字符如何編碼:

d53385be-fc02-11ee-a297-92fbcf53809c.jpg

但ASCII碼用來(lái)編碼字符效果不錯;拿來(lái)存儲數字卻極為浪費。比如它需要三個(gè)字節才能表示123。

為了編碼數字,我們需要一個(gè)更有效的方案。

一種很自然的想法是,我們就直接把二進(jìn)制對應的數字值拿來(lái)用,這就是最好的編碼方案!

于是,8個(gè)二進(jìn)制位就可以表示0~255之間的所有數字——用ASCII碼三個(gè)字節才能表示的123,直接用二進(jìn)制編碼就是01111011,一個(gè)字節足夠了。

這個(gè)方案只能表示正數;遇到負數怎么辦呢?

簡(jiǎn)單,第一個(gè)二進(jìn)制位拿出來(lái)當符號位,剩下七位仍然當數字用,就能表示±127之間的任何數字了。

這個(gè)方案就叫“原碼”;其中不帶符號位的就是無(wú)符號數(unsigned)。

原碼是一種很初級的編碼方案,它僅僅解決了編碼問(wèn)題——從此數字有辦法二進(jìn)制表示了。

但我們在計算機內部表示數字是用來(lái)計算的;那么想用原碼計算的話(huà),那可就麻煩了……

我們知道,最初CPU的內部最重要的核心器件叫ALU(Arithmetic and Logic Unit算術(shù)邏輯單元),其中的A就是數學(xué)。

ALU的核心是加法器,這是個(gè)隨參與計算的數值的二進(jìn)制位數指數增長(cháng)的數字電路。較早期的CPU里面絕大多數的邏輯門(mén)都被拿來(lái)做這個(gè)加法器了。

加法器顧名思義只能拿來(lái)做加法。

但是沒(méi)關(guān)系,如果你調過(guò)機械表,就知道從8點(diǎn)調到1點(diǎn)的方式有兩種:一種是往后撥7個(gè)小時(shí),一種是往前撥5個(gè)小時(shí)。

換句話(huà)說(shuō),在時(shí)鐘鐘面上,8-7和8+(12-7)效果相同,最終得到的都是1.

類(lèi)似的,1個(gè)字節的加減法,如果計算結果超過(guò)255就會(huì )造成溢出,溢出的高位二進(jìn)制數據無(wú)處存放自動(dòng)丟棄,計算結果就出錯了——但反過(guò)來(lái)想,這不恰恰就是一個(gè)邏輯鐘面嗎?

顯然,我們也可以利用這個(gè)性質(zhì)做減法:減32完全可以當成加(256-32)來(lái)算嘛;而由于二進(jìn)制的特點(diǎn),256-32恰好又等于32這個(gè)數值取反。

類(lèi)似的,有符號數其實(shí)是一個(gè)符號位和7個(gè)二進(jìn)制位,7個(gè)二進(jìn)制位能表示的最大數是127;因此減32就可以用加(128-32)代替(和表盤(pán)上的12點(diǎn)/0點(diǎn)一樣)。

于是,減法器就可以不做,一個(gè)加法器就足夠用了——省了好大一坨門(mén)電路,CPU的制造成本一下子就去了一大塊。

既然最終減法一定要這樣做……那么從一開(kāi)始就不應該用原碼表示負數,對吧。

不然每次計算都還得用一條指令判斷判斷符號位,然后該取反取反……這速度可就慢下去了。

如果從一開(kāi)始,負數就取反表示,那么負數加法完全無(wú)需判斷,拎起來(lái)就加——圓滿(mǎn)。

這個(gè)編碼方案就是所謂的反碼。

反碼是一個(gè)充滿(mǎn)了工程師的惡臭味的優(yōu)秀方案。

說(shuō)它優(yōu)秀,是因為它的確解決問(wèn)題;說(shuō)它惡臭,是因為它用起來(lái)實(shí)在麻煩,需要很多“微妙”的調整才能得到正確結果。

比如,它的符號位相加后,如果產(chǎn)生了進(jìn)位,就要把進(jìn)位送回去加到最低位上——你得搞一大張真值表才能確定這個(gè)做法的正確性。

嗯……這就是最容易產(chǎn)生沒(méi)人看得懂但絕對不能動(dòng)不然就會(huì )出錯的神奇代碼的重災區——反正它就是能工作;剛開(kāi)始我還知道為什么得這樣做,一段時(shí)間后就只有上帝知道了。

反碼行為奇特的根本原因在于,它有兩個(gè)零:+0和-0,分別對應于00000000和10000000——還記得嗎?我們規定第一位是符號位。因此最前面的0/1是±號,并不是數值。

但+0和-0都是0.它們是同一個(gè)數據,卻得到了兩個(gè)碼點(diǎn)。

打個(gè)比方的話(huà),這就好像夜里12點(diǎn)就是0點(diǎn)一樣;結果我們的鐘匠師傅沒(méi)想明白,偏偏要在鐘面上、12點(diǎn)和1點(diǎn)之間添加一個(gè)零點(diǎn)——然而邏輯上我們仍然需要12小時(shí)是一圈。

現在,你還想好好調表嗎?算的準準的,8點(diǎn)前擰5個(gè)小時(shí)就是1點(diǎn)了;結果擰完一看,0點(diǎn)?

徹底亂套了,對吧。

而反碼的計算規則呢,無(wú)異于規定了過(guò)12點(diǎn)的方向——正著(zhù)過(guò)正常去1點(diǎn),反著(zhù)過(guò)會(huì )先停在-0點(diǎn)上,所以必須推一把。

注意這個(gè)調整是計算過(guò)程的一部分,每次計算都必須即時(shí)調整。這是一個(gè)額外的負擔——和顯示時(shí)查表轉換到光學(xué)點(diǎn)陣/向量是不想干的兩個(gè)過(guò)程。

或者說(shuō),數據的內部表示和外部顯示之間的轉換是另外一個(gè)必不可少的流程。這里只要不是太過(guò)復雜就不能算額外負擔;而原碼/反碼這兩個(gè)編碼方案已經(jīng)影響了計算過(guò)程,造成了額外的性能消耗。

一言以蔽之:能解決問(wèn)題,但是太難看、太復雜。

一個(gè)更好的方案叫補碼。

但是在介紹補碼之前,我先來(lái)講一個(gè)數學(xué)概念—群。

群大概來(lái)源于“算術(shù)運算以及適用算法運算的集合”的抽象,但又超脫于簡(jiǎn)單的四則運算,是一切計算/變換類(lèi)似行為的總綱。

在群的觀(guān)念里,加減乘除都是一種“二元運算”;二元運算是一個(gè)集合G中任意兩個(gè)元素向群中另一個(gè)元素的映射。比如1+1就映射到了2。

注意群有“封閉性”,意思是群中任意兩個(gè)元素經(jīng)過(guò)二元運算后,映射的那個(gè)元素都還要在群中。因此(自然數,加減法)就不是一個(gè)群,因為減法會(huì )映射到負數。

此外,二元運算需要滿(mǎn)足結合律,要有單位元(任何元素與之執行二元運算后都會(huì )映射到該元素自身),等等。

更復雜的東西我也還看不懂(對不起,俺數學(xué)水平太弱雞了);但了解這么多其實(shí)也已經(jīng)夠了:反碼存在兩個(gè)0,意味著(zhù)對于加法運算來(lái)說(shuō),它存在兩個(gè)不同的單位元;而根據群的定義,群里面有且只有一個(gè)單位元。

因此,在反碼這個(gè)基礎上無(wú)法定義一個(gè)群——用人話(huà)說(shuō)就是,你不可能期望找到一種不需要判斷的算法,從而基于反碼模擬加減法運算。

沒(méi)錯,反碼有兩個(gè)零這事并不像外行想象的那樣無(wú)關(guān)痛癢——它并不僅僅是浪費了一個(gè)碼點(diǎn)的問(wèn)題,而是破壞了相關(guān)結構的性質(zhì)的問(wèn)題。

如何解決這個(gè)問(wèn)題呢?

不妨返璞歸真,看看這個(gè)問(wèn)題的本質(zhì)。

很簡(jiǎn)單,和上面等待寫(xiě)入時(shí)間信息的無(wú)字鐘面一樣:這里有256個(gè)不同的二進(jìn)制編碼,我們需要給它們分別指定一個(gè)意義。

我們希望它們是連續的編碼,且基于二進(jìn)制的排序不能打亂——這樣我們才能使得基于這些碼點(diǎn)的、拋棄溢出位的加減法運算構成一個(gè)群。

只有它們是一個(gè)群,我們才能簡(jiǎn)單明了的在加法器上支持加減法運算——而不是先算一個(gè)瑕疵值然后想辦法彌補、把硬件/軟件變得復雜。

打個(gè)比方的話(huà),就是把這些二進(jìn)制編碼按順序排于鐘面,我們要在上面填上帶±號的數字。

原碼的問(wèn)題在于,它的編碼排列“不按固定順序”,使得因此必須把負數先“顛倒”一下(實(shí)際上取反)才能用;而反碼頭疼醫頭腳疼醫腳,大致保證了編碼順序,卻沒(méi)能消除額外的無(wú)效碼點(diǎn),造成在±0這個(gè)位置兩個(gè)碼點(diǎn)對應一個(gè)編碼。

這兩個(gè)編碼都沒(méi)法自然構造出加法群。

借用@任衛同學(xué)的這張圖:

d5543caa-fc02-11ee-a297-92fbcf53809c.jpg

可以很清晰的看出補碼編碼的連續性。

(相比之下,原碼是0 1 2 3……127 -0 -1 -2……-127,順序上一會(huì )兒從小到大一會(huì )兒從大到??;補碼按照一定的順序編碼但是多了個(gè)-0;

只有補碼,嚴格按照統一的順序連續排列數字)。

既然連續,那么通過(guò)加一個(gè)值(可能為負)調整對稱(chēng)中心(比如0的位置是00000000還是11111111)、然后再引入模運算剔除高位溢出,這個(gè)群就建立起來(lái)了。

換句話(huà)說(shuō),隨便你如何編碼,只要別改變底層的二進(jìn)制順序、不要有跳躍/重復碼點(diǎn),那么這個(gè)計算就仍然是一個(gè)群。

這個(gè)計算過(guò)程和最終的顯示是完全脫鉤的,你不需要在計算時(shí)做任何調整——溢出就隨它溢出,反正(在模運算的層面上)算出來(lái)的值總是對的。這是群的性質(zhì)所保證的。

(注意是“模運算的層面上”,換句話(huà)說(shuō)算出來(lái)的實(shí)際意義是什么還是得你自己解釋?zhuān)挥绕涫钱a(chǎn)生溢出之后。)

比如,哪怕你把它的編碼范圍改成[-129, 126]或者[-1, 254],這也僅僅是一個(gè)加/減一個(gè)整數的映射操作而已;核心計算法則仍然會(huì )滿(mǎn)足你的需求)。

甚至,你規定0代表1、1代表0,最終也不過(guò)是顯示時(shí)換一個(gè)不同的譯碼表而已,并不改變問(wèn)題性質(zhì)。

這個(gè)性質(zhì)是普適的。

7位、8位或者32位、128位二進(jìn)制全都適用。

一旦明白了這個(gè)……再寫(xiě)環(huán)形緩沖時(shí),你還要費勁巴拉的檢查什么時(shí)候需要繞回嗎?求個(gè)余(或許還需要再視情況不同增減一個(gè)常數),完事。

你看,數學(xué)這種東西厲害吧?

哪怕群論門(mén)檻都摸不到的這么一點(diǎn)點(diǎn)皮毛知識,帶來(lái)的就是眼界水平的差異。

一旦了解了這點(diǎn)皮毛,關(guān)于補碼的種種清規戒律神奇規則,也就平常。

但沒(méi)有這個(gè)眼界,就容易像反碼那樣動(dòng)輒得咎;反之,隨你怎么玩都不會(huì )出界。

沒(méi)錯。別看這東西簡(jiǎn)單;

但想要做第一個(gè)提出的人,你還是需要強悍的洞察力的。

站在群論的肩膀上、反向碾壓這個(gè)問(wèn)題,這是伽羅瓦之后的現代人特有的福利。

審核編輯:黃飛

聲明:本文內容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權轉載。文章觀(guān)點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習之用,如有內容侵權或者其他違規問(wèn)題,請聯(lián)系本站處理。 舉報投訴
  • cpu
    cpu
    +關(guān)注

    關(guān)注

    68

    文章

    10525

    瀏覽量

    207451
  • 邏輯門(mén)
    +關(guān)注

    關(guān)注

    1

    文章

    127

    瀏覽量

    23886
  • 加法器
    +關(guān)注

    關(guān)注

    6

    文章

    179

    瀏覽量

    29835
  • ASCII
    +關(guān)注

    關(guān)注

    5

    文章

    169

    瀏覽量

    34723
  • 減法器
    +關(guān)注

    關(guān)注

    1

    文章

    26

    瀏覽量

    16725

原文標題:為什么8位數據范圍是-128到127,而不是-127到128?

文章出處:【微信號:嵌入式情報局,微信公眾號:嵌入式情報局】歡迎添加關(guān)注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關(guān)推薦

    各位大哥幫忙看下??!此函數賦值有無(wú)問(wèn)題(8位數據接口為PB8-15)

    = 0;//傳送u16變量value高8位數據PB8-15 GPIOB->BSRR = value & 0xff00;GPIOB->BRR = (~value) &
    發(fā)表于 09-16 19:11

    請問(wèn)HT1621驅動(dòng)芯片內部RAM中的4位數據表示什么?

    HT1621驅動(dòng)芯片內部RAM中的4位數據表示什么?就我理解的話(huà)每個(gè)seg信號是確定哪一個(gè)段亮,而對應地址的數據究竟是控制什么的?
    發(fā)表于 07-04 17:35

    PIC18F2550硬件EUSART具有6位數據

    你好!我可以使用PIC18F2550硬件EASART,用6位數據、1奇偶校驗和2個(gè)停止為老從設備。在數據表6位數據模式中找不到,它在幀中
    發(fā)表于 12-04 13:40

    請問(wèn)FPGA如何串行接收16或32位數據?

    這個(gè)問(wèn)題困擾我好多天了 串口通信只能一次接收8位數據,而如果接收16或32數據,那么得通過(guò)串口接收2個(gè)或4個(gè)
    發(fā)表于 05-27 23:25

    請問(wèn)光流傳感器輸出的dx,dy的16位數據指的是什么值?

    我買(mǎi)了一個(gè)原子剛出的光流模塊搭載在配套的小四軸上,感覺(jué)飛的很穩,最近在看光流的程序,有一點(diǎn)不太明白,光流傳感器輸出的dx,dy的16位數據指的是什么值?dx,dy應該是x和y方向的位移,用十六位數據表示的是什么值?有哪位大神可以回答一下嗎?
    發(fā)表于 07-17 02:11

    數據表表示列表上最多只能有8個(gè)設備嗎

    數據表表示列表上最多只能有8個(gè)設備嗎
    發(fā)表于 10-17 22:19

    C語(yǔ)言單片機編程為什么總是用無(wú)符號的數據類(lèi)型來(lái)定義

    注意:答案和題目均轉自百度知道char型可以表示數的范圍是-128127,所占位數
    發(fā)表于 07-01 08:07

    關(guān)于單片機位數的思考(8、16、32)精選資料分享

    8、16、32是指單片機的“字長(cháng)”,也就是一次運算中參與運算的數據長(cháng)度,這個(gè)位是指二進(jìn)制
    發(fā)表于 07-15 09:01

    NUC442使用SPI做Master連續發(fā)送8位數據,示波器觀(guān)察每發(fā)送完成8位數據中間會(huì )有幾個(gè)微秒的延時(shí)時(shí)間是為什么?

    NUC442使用SPI做Master連續發(fā)送8位數據,示波器觀(guān)察每發(fā)送完成8位數據中間會(huì )有幾個(gè)微秒的延時(shí)時(shí)間,另外,啟動(dòng)SPI發(fā)送后也會(huì )有
    發(fā)表于 06-20 06:21

    AD5544的18位數據由2bit地址和16位數據位組成,采用標準SPI的時(shí)候一次傳輸8位數據該如何傳輸呢?

    AD5544的18位數據由2bit地址和16位數據位組成,采用標準SPI的時(shí)候一次傳輸8位數據該如何傳輸呢?是從17-0
    發(fā)表于 12-19 08:08

    數據表示—常用的信息編碼

    數據表示—常用的信息編碼 一.邏輯數據表示 邏輯數據是用來(lái)表示二值邏輯中的“是”與“否”或
    發(fā)表于 04-15 14:36 ?2129次閱讀

    ADV7196A:多格式逐行掃描/HDTV編碼器,3個(gè)11位DAC,10位數據輸入和宏視數據表

    ADV7196A:多格式逐行掃描/HDTV編碼器,3個(gè)11位DAC,10位數據輸入和宏視數據表
    發(fā)表于 04-23 17:22 ?2次下載
    ADV7196A:多格式逐行掃描/HDTV<b class='flag-5'>編碼</b>器,3個(gè)11位DAC,10<b class='flag-5'>位數據</b>輸入和宏視<b class='flag-5'>數據表</b>

    AD7376:+30 V/±15 V操作128位數字電位器數據表

    AD7376:+30 V/±15 V操作128位數字電位器數據表
    發(fā)表于 05-16 17:51 ?2次下載
    AD7376:+30 V/±15 V操作<b class='flag-5'>128</b><b class='flag-5'>位數</b>字電位器<b class='flag-5'>數據表</b>

    603-24-127 數據表

    603-24-127 數據表
    發(fā)表于 05-15 18:35 ?0次下載
    603-24-<b class='flag-5'>127</b> <b class='flag-5'>數據表</b>

    603-24-127 數據表

    603-24-127 數據表
    發(fā)表于 07-11 19:45 ?0次下載
    603-24-<b class='flag-5'>127</b> <b class='flag-5'>數據表</b>
    亚洲欧美日韩精品久久_久久精品AⅤ无码中文_日本中文字幕有码在线播放_亚洲视频高清不卡在线观看