2010-06-11 97 views
8

有人可以向我解釋我如何將32位浮點值轉換爲16位浮點值?Float32到Float16

(S =符號E =指數且m =尾數)

如果32位浮點是1s7e24m
和16位浮點數是1s5e10m

然後是它那樣簡單做什麼?

int  fltInt32; 
short fltInt16; 
memcpy(&fltInt32, &flt, sizeof(float)); 

fltInt16 = (fltInt32 & 0x00FFFFFF) >> 14; 
fltInt16 |= ((fltInt32 & 0x7f000000) >> 26) << 10; 
fltInt16 |= ((fltInt32 & 0x80000000) >> 16); 

我假設它不是那麼簡單...所以任何人都可以告訴我你需要做什麼?

編輯:我相信我的指數轉移錯了......所以這會更好嗎?

fltInt16 = (fltInt32 & 0x007FFFFF) >> 13; 
fltInt16 |= (fltInt32 & 0x7c000000) >> 13; 
fltInt16 |= (fltInt32 & 0x80000000) >> 16; 

我希望這是正確的。如果我錯過了一些已經說過的話,我很抱歉。它在星期五晚上幾乎是午夜...所以我不是「完全」清醒的;)

編輯2:Ooops。又犯了一個錯誤。我想失去前三位而不是更低!那麼這個怎麼樣:

fltInt16 = (fltInt32 & 0x007FFFFF) >> 13; 
fltInt16 |= (fltInt32 & 0x0f800000) >> 13; 
fltInt16 |= (fltInt32 & 0x80000000) >> 16; 

最終代碼應該是

fltInt16 = ((fltInt32 & 0x7fffffff) >> 13) - (0x38000000 >> 13); 
fltInt16 |= ((fltInt32 & 0x80000000) >> 16); 
+2

我認爲這已經在這裏問(和回答):http://stackoverflow.com/questions/1659440/32-bit-to-16-bit-floating-point-conversion – humbagumba 2010-06-11 21:54:51

+0

它可能是那麼簡單,但你會失去精度,除非float32沒有使用它所具有的所有「精度」......基本上,你可以獲得5/7的exp(你當然是最有意義的)和10/24的尾數;這些比率說不定,你可以在轉換中放鬆多少。就像它發生的情況一樣,如果你想將32位整數合併到一個16位整數中......可擴展數字的範圍更小; 「削減」尾數會降低「精度」,而指數也會限制範圍:5個有符號位給出-16到+15,反對-64/+ 63(如果我做對了......:D遲到了) – ShinTakezou 2010-06-11 21:58:25

+0

@ShinTakezou:當然它不可能丟失16位數據而不會失去精度? Float16遠不夠精確,因此自動精度降低......或者我誤解了你? – Goz 2010-06-11 22:01:45

回答

4

該指數在FLOAT32和float16表示可能是偏見,和有偏見的不同。您需要取消您從float32表示中獲得的指數以獲取實際指數,然後將其偏置爲float16表示形式。

除了這個細節之外,我確實認爲它非常簡單,但我仍然會時常浮現浮點表示。

編輯:

  1. 與指數做的事情時,而你在它檢查是否溢出。

  2. 你的算法有點突然地截斷了mantisa的最後幾個比特,這可能是可以接受的,但是你可能想通過查看即將被丟棄的比特實現,比如舍入到最近。 「0 ...」 - >向下舍入,「100..001 ...」 - >向上舍入,「100..00」 - >舍入到偶數。

+0

IEEE754標準中的32位浮點數有23位尾數和8位指數。 – bbudge 2010-06-11 21:57:43

+0

@bbudge ...足夠公平我試圖從記憶中做到這一點。顯然,我錯了一些;) – Goz 2010-06-11 22:02:43

4

的指數必須是公正的,夾緊並rebiased。這是快速的代碼我使用:

unsigned int fltInt32; 
unsigned short fltInt16; 

fltInt16 = (fltInt32 >> 31) << 5; 
unsigned short tmp = (fltInt32 >> 23) & 0xff; 
tmp = (tmp - 0x70) & ((unsigned int)((int)(0x70 - tmp) >> 4) >> 27); 
fltInt16 = (fltInt16 | tmp) << 10; 
fltInt16 |= (fltInt32 >> 13) & 0x3ff; 

該代碼將是更快與指數查找表,但我用這一個,因爲它很容易適應一個SIMD工作流程。實施

限制:不能在float16表示會給不定值

  • 溢出值。
  • 下溢值將在2^-152^-14之間返回一個未定義的值,而不是零。
  • 反規範將給出未定義的值。

注意非正常化。如果你的架構使用它們,它們可能會極大地減慢你的程序。