C++17 添加十六进制浮点常量 ( floating point literal )。为什么?举几个例子来说明好处如何。

最佳答案

浮点数存储在 x86/x64 处理器中,基数为 2,而不是基数 10: https://en.wikipedia.org/wiki/Double-precision_floating-point_format 。由于无法准确表示许多十进制浮点数,例如十进制 0.1 可以表示为 0.1000000000000003 或 0.0999999999999997 之类的东西 - 任何具有足够接近十进制 0.1 的基数表示的东西。由于这种不精确性,例如以十进制打印然后解析浮点数可能会导致与打印前以二进制方式存储在内存中的数字略有不同。

对于某些应用程序出现此类错误是 Not Acceptable :他们希望解析为与打印前完全相同的二进制浮点数(例如,一个应用程序导出浮点数据而另一个导入)。为此,可以以十六进制格式导出和导入 double 数。因为 16 是 2 的幂,所以二进制浮点数可以精确地以十六进制格式表示。
printfscanf 已经扩展了 %a 格式说明符,允许打印和解析十六进制浮点数。虽然 MSVC++ does not support %a format specifier for scanf 还没有:



要以十六进制格式以全精度打印 double,应指定在点后打印 13 个十六进制数字,对应于 13*4=52 位:

double x = 0.1;
printf("%.13a", x);

查看有关 hexadecimal floating point with code and examples 的更多详细信息(请注意,至少对于 MSVC++ 2013,%aprintf 的简单规范会在点后打印 6 个十六进制数字,而不是 13 - 这在文章末尾说明)。

特别是对于常量,如问题中所问,十六进制常量可能便于在精确的硬编码浮点输入上测试应用程序。例如。您的错误可能可以重现 0.1000000000000003,但不能重现 0.0999999999999997,因此您需要十六进制硬编码值来指定对十进制 0.1 感兴趣的表示。

10-04 21:17
查看更多