【问题标题】:Why hexadecimal floating constants in C++17?为什么在 C++17 中使用十六进制浮点常量?
【发布时间】:2016-04-01 04:46:39
【问题描述】:

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

【问题讨论】:

  • (1) 为了与 C 长期兼容(从 ISO C99 开始) (2) 为了明确 定义浮点常量(用于 IEEE-754 二进制浮点特别是格式),没有经常影响从十进制浮点转换的错误(有关现代常用软件中此类错误的示例,请参阅Rick Regan's blog
  • 需要明确指定文字浮点常量的示例是为数学库函数创建代码,例如atanf, erff, expf

标签: c++ floating-point constants c++17


【解决方案1】:

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

对于某些应用程序出现此类错误是不可接受的:他们希望解析为与打印前完全相同的二进制浮点数(例如,一个应用程序导出浮点数据而另一个应用程序导入)。为此,可以以十六进制格式导出和导入双精度数。因为 16 是 2 的幂,所以二进制浮点数可以用十六进制格式精确表示。

printfscanf 已扩展为 %a 格式说明符,允许打印和解析十六进制浮点数。虽然MSVC++ does not support %a format specifier for scanf还没有:

scanf 不提供 a 和 A 说明符(请参阅 printf 类型字段字符)。

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

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

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

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

【讨论】:

  • 文中展示的例子是针对gcc的。在文章的最后一段中,我说在 VC++ 中使用“%.13a”而不是“%a”。
  • @RickRegan,抱歉,最初没有注意到文章的结尾。我已经编辑了我的答案。
  • 请注意,1 在基数 a 中的所有浮点数都可以在基数 b 中表示当且仅当 b 可以被 a2 的所有素数整除所以以 2 为底的所有数字也可以以 10 为底精确表示,3 17 位十进制数字足以让double 往返。
【解决方案2】:

在十进制上使用十六进制浮点数的两个主要原因是准确性和速度。

在十进制常量和浮点数的底层二进制格式之间进行精确转换的算法是surprisingly complicated,甚至现在conversion errors still occasionally arise

十六进制和二进制之间的转换要简单得多,而且保证是准确的。一个示例用例是当您使用特定的浮点数而不是任何一侧(例如,用于实现特殊功能,如 exp)时至关重要。这种简单性也使转换速度更快(它不需要任何中间的“bignum”算术):在某些情况下,我看到十六进制浮点数与小数的读/写操作速度提高了 3 倍。

【讨论】:

  • 我不明白这如何使代码更快。例如。 0xA.0f 在位级别上应该完全10.0f 相同,那么源代码表示如何可能使实现更快?为什么要进行任何运行时转换?
  • 我的意思是如果您使用的是printffscanf
  • 等一下,如果一个平台使用 base2 浮点数而其他平台使用十进制浮点数怎么办? ieee 754 假设各种格式
  • 在硬件中支持十进制浮点数的平台并不多,而那些仍然倾向于将二进制浮点数作为默认值,将十进制作为次要类型。
  • 重新“保证准确”:当然,前提是有足够的位来表示。 |问题是关于constant,而不是reading/writing
猜你喜欢
  • 2021-05-04
  • 2011-07-25
  • 2012-06-10
  • 2011-12-05
  • 2014-02-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多