浮點數(shù)和定點數(shù)的相互轉(zhuǎn)換
掃描二維碼
隨時隨地手機看文章
浮點數(shù)量化為定點
1. 這篇博客將要討論什么?
說來慚愧,作為計算機科班出身的人,計算機基礎(chǔ)知識掌握并不扎實,這里的基礎(chǔ)指的是計算機體系結(jié)構(gòu)中的內(nèi)容,諸如數(shù)據(jù)的表示和處理,如float的表示和運算等。看《CSAPP》方知人家老外把這個東西當(dāng)成重中之重,大量詳細(xì)的原理介紹,并配套大量例題。當(dāng)初本科學(xué)的時候,很簡單的了解了下概念而已,所以應(yīng)該直接將《CSAPP》當(dāng)做教材來用,里面習(xí)題全做,這樣CS出來的基本知識將掌握的很扎實。
學(xué)藝不精的后果就在于:學(xué)而不思則罔。圣人太厲害了,總結(jié)得很到位。比如最近項目中涉及到浮點和定點的轉(zhuǎn)換,自己就有點蒙,邊看邊實驗,還算理解了,作文以記之。
一直以來,程序中接觸的數(shù)據(jù)類型都是int整型,char字符型,float單精度浮點型,double雙精度浮點型??吹礁↑c和定點一直不知道如何劃分這個概念的范疇。以為浮點就是float表示小數(shù),定點就是int可表示整數(shù)而已。經(jīng)過學(xué)習(xí)明白了顯然是錯誤的。應(yīng)該是這樣劃分的:
浮點:小數(shù)點非固定的數(shù),可表示數(shù)據(jù)范圍較廣,整數(shù),小數(shù)都可表示。包含float,double;
定點:小數(shù)點固定,可表示整數(shù),小數(shù)。int本質(zhì)是小數(shù)點位于末尾的32位定點數(shù)而已;
有了這個認(rèn)識,后面的討論就可以開始了。
2. 浮點數(shù)的表示法
浮點數(shù)以float為例討論。
2.1 IEEE 754標(biāo)準(zhǔn)
規(guī)定浮點數(shù)格式為:
s表示符號位,當(dāng)s=0,V為正數(shù);當(dāng)s=1,V為負(fù)數(shù)
M表示尾數(shù),2>M>=1
E表示階碼
將其封裝到32位的字中:
根據(jù)32位數(shù)計算為十進制:
可以得出以下結(jié)論:
浮點數(shù)表示比整型那些更為復(fù)雜。如int中0…01000表示8,0…01001表示9,而浮點不能這樣簡單。
浮點數(shù)不能移位。因為各個位有特殊含義。像int數(shù)乘2可以左移1位實現(xiàn)。
2.2 浮點數(shù)的“浮”字體現(xiàn)在哪里?
我們說浮點數(shù)的小數(shù)點不是固定的,是浮動的,那么如何理解?通過例子可直觀體驗。
這個浮點數(shù)表示十進制的1.125
若階碼不變,尾數(shù)加1,則表示十進制的1.25
若尾數(shù)不變,階碼加1,則表示十進制的2.25
3. 定點數(shù)的表示法
對于計算機來說,浮點定點的概念是看不見的,因為它只能看到:0…00001110,至于它表示多少,是邏輯層面的設(shè)置。你如果讓它是int那就按照int表示法對每個位賦予意義,如果你讓它是float就按照float表示法賦予意義。
對于000111000001110000011100表示的定點數(shù):
如果我們設(shè)定小數(shù)點是位于最后一位的,即00011100.00011100.00011100.則其表示28
若設(shè)定小數(shù)點位于后三位的,即00011.10000011.10000011.100則其表示3.50
若設(shè)定小數(shù)點位于后四位的,即0001.11000001.11000001.1100則其表示1.75
可以看到:
小數(shù)位數(shù)越多,表示的精度越高。若小數(shù)點后有n位,則其表示的最大精度為
1/(2n);
整數(shù)位數(shù)越多,可表示的最大值越大。
以8位為例,最高位為符號位:
若整數(shù)位占4位,小數(shù)位占3位,則其最大精度為0.125,最大值為15.875
若整數(shù)位占5位,小數(shù)位占2位,則其最大精度為0.250,最大值為31.750
若整數(shù)位占6位,小數(shù)位占1位,則其最大精度為0.500,最大值為63.500
若整數(shù)位占7位,小數(shù)位占0位,則其最大精度為1.000,最大值為127
4. 浮點數(shù) & 定點數(shù)
4.1 為何要把浮點數(shù)轉(zhuǎn)換為定點數(shù)呢?
這來源于項目中神經(jīng)網(wǎng)絡(luò)的需求,網(wǎng)絡(luò)中大量的參數(shù),如果全部用F32表示,一是占用空間大,二是讀取效率不高。
如果我們可以將某些浮點數(shù)轉(zhuǎn)換為定點數(shù)表示,在接受精度損失的前提下,每次就可以讀取多個進行運行,可顯著提高運算效率。
舉例來說,我們用8位定點數(shù),1個符號位,4個整數(shù)位,3個小數(shù)位,則其可表示范圍是-16.00~15.875,最大精度0.125。
有幾個浮點數(shù):0.145,1.231,2.364,7.512,每個需要32bit表示。
如果我們將每個量化成一個8位定點數(shù),比如通過某種方法得到:1,10,19,60
此時每個數(shù)需要8bit表示。那么讀一個浮點數(shù),可以同時讀4個定點數(shù),且計算效率可以提高。當(dāng)然這樣做是有風(fēng)險的:
損失精度,比如再將上述定點數(shù)轉(zhuǎn)化為浮點數(shù):0.125,1.250, 2.375,7.500;
定點數(shù)表示范圍有限,加法有可能會溢出,需要拿int16或int32來暫存中間結(jié)果;
4.2 如何將浮點數(shù)轉(zhuǎn)換為定點數(shù)?
我們用8位定點數(shù),1個符號位,4個整數(shù)位,3個小數(shù)位。這個3稱為量化系數(shù)。該過程稱為量化。
(我們總是將非離散值量化到離散值空間,處理更為簡單)
Int8=float32*2(3)
如:
Int8(10)=float32(1.231)*2(3)
4.3 如何將定點數(shù)轉(zhuǎn)換為浮點數(shù)?
該過程稱為反量化。
Float32=int8/2(3)
如:
Float32(1.250)=int8(10)/2(3)
4.4 note
可以這樣理解:量化系數(shù) nnn 決定了我們邏輯上認(rèn)為01序列中可表示的單位值 1/(2n),CPU讀取的數(shù)字表示有多少份單位值。
舉例來說,對于固定的01序列值:0001,1100
同樣的int8數(shù),因為量化系數(shù)的不同,代表著不同的f32值。
還有個note:
定點數(shù)加減時需要量化系數(shù)相同,其值有可能溢出,需要更大定點數(shù)來暫存中間值;
兩個定點數(shù)乘法后如果需要轉(zhuǎn)化為f32,則反量化系數(shù)變?yōu)?/span>2?n
5. 總結(jié)
可以看到:
浮點數(shù)和定點數(shù)的轉(zhuǎn)換是一種映射。將較為密集的數(shù)據(jù)空間(F32)映射到較為稀疏的空間(int8);
定點數(shù)的小數(shù)點實際中是沒有的,這只是我們邏輯上的一種設(shè)定。01序列是一樣的,CPU讀取都是相同的,因為我們邏輯上小數(shù)點的不同位置,我們認(rèn)為它代表的值是不同的;
作者:鳥戀舊林XD
原文鏈接:https://blog.csdn.net/niaolianjiulin/article/details/82764511
最后給大家一個在線的轉(zhuǎn)換工具:
https://www.h-schmidt.net/FloatConverter/IEEE754.html
示例:將浮點數(shù)55.12345轉(zhuǎn)換為32bit