【发布时间】:2017-07-25 06:14:47
【问题描述】:
首先,IEEE754 半精度浮点数使用 16 位。它使用 1 位符号、5 位指数和 10 位尾数。实际值可以计算为符号 * 2^(exponent-15) * (1+mantisa/1024)。
我正在尝试使用半精度运行图像检测程序。原始程序使用单精度 (=float)。我在http://half.sourceforge.net/ 中使用半精度类。使用 half 类,我至少可以运行相同的程序。(通过使用 half 代替 float 并使用 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中,我认为有些人只是将每个问题都视为同一个老问题,而实际上情况略有不同。并且有几个类似的问题并没有什么坏处。)
【问题讨论】:
-
"用 g++ 编译而不是 gcc" 那是因为你使用的是 C++ 头文件库。另外你的
main定义是错误的,它应该是int main。它会产生错误的输出,因为您正在转换为float- 尝试使用库网站上示例中所述的std::cout,或使用half_cast(也由库提供) -
恕我直言,在研究图像检测或浮点数之前,您应该先学习编程。如果没有基本的编程技能和工具中的基本知识,您将无法产生可靠的结果。
-
@NickyC 我忘了 int main() return 0;当我发布问题时。我有时使用 C++ 代码,但这些天使用 C。我认为我不应该再次“学习”编程。只是我在工作期间在不同的语言之间切换,C、C++、Python、verilog、VHDL 等。而且因为原始源代码是 C,所以我试图尽可能地维护代码。这是一个包含许多文件的巨大 C 程序。
-
请(学习)阅读您尝试使用的库的文档。只是随意编写代码并希望它能够工作不是创建软件的好方法。
-
为什么你认为结果是错误的?你期望它是什么? (十位尾数的精度非常有限,并且 w_scale 略小于 1.847656。您还要对输出进行四舍五入。)
标签: c++ precision numeric ieee-754