2017-07-25 79 views
-2

首先,IEEE754半精度浮點數使用16位。它使用1位符號,5位指數和10位尾數。實際值可以計算爲符號* 2 ^(指數-15)*(1 + mantisa/1024)。
我試圖運行一個圖像檢測程序使用半精度。原始程序使用單精度(=浮點數)。我在http://half.sourceforge.net/中使用半精度類。使用類的一半,我至少可以運行相同的程序(通過使用一半而不是浮點數,並用g ++而不是gcc編譯,並且在許多類型鑄造之後..)
我發現一個問題,乘法似乎是錯誤的。半精度多項式似乎產生錯誤結果

這裏是查看問題的示例代碼(要打印半精度數字,我應該將其轉換爲浮點數以查看值,並且自動轉換不會在半角和整數的操作中發生,因此我將一些鑄件..):

#include <stdio.h> 
#include "half.h" 
using half_float::half; 
typedef half Dtype; 

main() 
{ 
#if 0 // method 0 : this makes sx 600, which is wrong. 

int c = 325; 
Dtype w_scale = (Dtype)1.847656; 
Dtype sx = Dtype(c*w_scale); 
printf("sx = %f\n", (float)sx); // <== shows 600.000 which is wrong. 

#else // method 1, which also produces wrong result.. 

int c = 325; 
Dtype w_scale = (Dtype)1.847656; 
Dtype sx = (Dtype)((Dtype)c*w_scale); 
printf("sx = %f\n", (float)sx); 
printf("w_scale specified as 1.847656 was 0x%x\n", *(unsigned short *)&w_scale); 

#endif 
} 

結果看起來是這樣的:

w_scale = 0x3f63 
sx = 600 
sx = 0x60b0 

但SX應該是325 * 1.847656 = 600.4882。什麼可能是錯誤的?

地址:當我第一次發佈這個問題時,我沒有想到它的值恰好是600.4882,而是接近它。後來我發現了半精度,它只能表達3〜4位有效數字,而最接近的數值只是600.00。雖然大家都知道浮點數有這種侷限性,但有些人會因爲忽視半精度只能有3〜4個有效數字的事實而犯我這樣一個錯誤。所以我認爲這個問題值得未來提問者看一看。 (在stackoverflow中,我認爲有些人只是把每個問題看作是同一個老問題,當它實際上是一個稍微不同的情況時,並且它不會帶來幾個類似問題。)

+1

*「用g ++而不是gcc編譯」*這是因爲您使用的是C++頭文件庫。另外你的'main'定義是錯誤的,它應該是'int main'。它會產生錯誤的輸出結果,因爲你正在轉換爲'float' - 嘗試使用庫中網站示例中描述的'std :: cout',或者使用'half_cast'(也由庫提供) – UnholySheep

+0

With all due尊重,在進行圖像檢測或浮點數的研究之前,您應該先學習編程。沒有基本的編程技能和工具基礎知識,就無法產生可靠的結果。 –

+0

@NickyC我忘了int main()return 0;當我發佈這個問題時。我有時使用C++代碼工作,但最近和C.一起工作,我認爲我不應該再次「學習」編程。這只是我在工作期間切換不同的語言,C,C++,Python,Verilog,VHDL等。並且由於原始源代碼是C語言,因此我儘可能地維護代碼。這是一個包含許多文件的巨大C程序。 –

回答

-1

我想明白了原因。半精度的有效精度約爲log10(2^10)〜3或4位數。我想將sx打印爲600.488或其他東西,但這不能用半精度表示。 這部分是在圖像預處理過程中進行的,可以在沒有16位精度的情況下完成(我們的試驗性硬件),所以我可以在這個階段使用浮點運算。
ADD:這個異常出現在圖像尺寸計算過程中,我們沒有任何理由在這種情況下使用16位浮點數。只有圖像數據(像素或特徵地圖數據)應該使用16位浮點數。寫完這些之後,這是一條通用規則。