假设您有一个像“0.1”这样的字符串,只能近似表示为二进制浮点数,并且您希望将其转换为单精度浮点数。这可以作为
strtof(s, 0);
或者
(float)strtod(s, 0);
直觉上,这些应该给出相同的结果,但是直觉在所有情况下都是正确的吗?或者是否存在任何极端情况,在这种情况下,第二种形式通过两次舍入,给出的结果与第一种形式略有不同?
假设您有一个像“0.1”这样的字符串,只能近似表示为二进制浮点数,并且您希望将其转换为单精度浮点数。这可以作为
strtof(s, 0);
或者
(float)strtod(s, 0);
直觉上,这些应该给出相同的结果,但是直觉在所有情况下都是正确的吗?或者是否存在任何极端情况,在这种情况下,第二种形式通过两次舍入,给出的结果与第一种形式略有不同?
C 标准对strtod
和的规范未充分说明strtof
。它为总是、经常或从不strtof
返回的可能性留出了空间。(float)strtod
(本段引用了包含该段的标准的另一部分,其中说“结果是最接近的可表示值,或者是与最近的可表示值直接相邻的更大或更小的可表示值,以实现定义的方式选择” )。
和返回的典型实现分别是最接近和最接近传递给它们的十进制表示。当这些函数以这种方式运行时, then几乎总是与 相同。据说它们不相同的十进制表示会出现双舍入问题,因为先将十进制表示四舍五入到再四舍五入与直接四舍五入到 产生不同的结果。请注意,当这种情况发生时,结果是更准确的结果。中间舍入使误差略大于 ULP 的一半,而不是略小于 ULP 的一半。strtod
strtof
double
float
strtof(s, 0)
(float)strtod(s, 0)
double
float
float
strtof
double
在转换为之前经历双舍入问题的十进制表示的一个示例float
是1.01161128282547
(取自此测验)。最近double
的正好在两个float
s 之间。直接四舍五入float
得到你最近的float
,并通过最近的double
产生另一个float
。
无论您使用什么类型,x86 FPU 始终使用 80 位浮点数。double
从 转换为甚至会产生额外的运行时成本float
。
我不确定,但strtof()
可以实现为 wrapper around strtod()
,所以我最好在你的地方使用strtof()
,而不是调用函数来解析为 double 然后转换为float
,以表明你的意图。如果您不信任编译器并且想要优化代码,那么使用 of 可能(float)strtod()
会为您节省一些额外call/ret
指令的性能。