半精度乘法似乎产生了错误的结果

half precision muliplication seems to produce wrong result

首先,IEEE754半精度浮点数使用16位。它使用 1 位符号、5 位指数和 10 位尾数。实际值可以计算为 sign * 2^(exponent-15) * (1+mantisa/1024).
我正在尝试 运行 使用半精度的图像检测程序。原始程序使用单精度(=float)。我在 http://half.sourceforge.net/ 中使用半精度 class。使用 class 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。有什么问题?

ADD : 当我第一次发布这个问题时,我没想到这个值恰好是 600.4882,而是接近它的某个地方。后来发现半精度,限制只能表示3~4个有效位数,乘法最接近的值刚好是600.00。虽然大家都知道浮点数有这种局限性,但有些人会像我一样犯错误,因为他们忽略了半精度只能有 3~4 位有效数字这一事实。所以我认为这个问题值得未来的提问者看看。 (在 Whosebug 中,我认为有些人只是把每个问题都当作同一个旧问题,而实际上情况略有不同。而且提出几个类似的问题也没什么坏处。)

我明白为什么了。半精度的有效精度约为 log10(2^10) ~ 3 或 4 位。我希望 sx 打印为 600.488 或接近的值,但这不能使用半精度表示。 这部分是在图像预处理过程中出现的,可以在没有 16 位精度的情况下完成(我们暂定的硬件),所以我可以在这个阶段使用 float 操作。
ADD :这个异常是在计算图像尺寸时出现的,我们没有任何理由在这种情况下使用 16 位浮点数。只有图像数据(像素或特征图数据)应该使用 16 位浮点数。写到这里,就是一般规则了。