2017-07-25 78 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位浮点数。写完这些之后,这是一条通用规则。