7

假设您有一个像“0.1”这样的字符串,只能近似表示为二进制浮点数,并且您希望将其转换为单精度浮点数。这可以作为

strtof(s, 0);

或者

(float)strtod(s, 0);

直觉上,这些应该给出相同的结果,但是直觉在所有情况下都是正确的吗?或者是否存在任何极端情况,在这种情况下,第二种形式通过两次舍入,给出的结果与第一种形式略有不同?

4

2 回答 2

6

C 标准对strtod和的规范未充分说明strtof。它为总是、经常或从不strtof返回的可能性留出了空间。(float)strtod本段引用了包含该段的标准的另一部分,其中说“结果是最接近的可表示值,或者是与最近的可表示值直接相邻的更大或更小的可表示值,以实现定义的方式选择” )。

和返回的典型实现分别是最接近和最接近传递给它们的十进制表示。当这些函数以这种方式运行时, then几乎总是与 相同。据说它们不相同的十进制表示会出现双舍入问题,因为先将十进制表示四舍五入到再四舍五入与直接四舍五入到 产生不同的结果。请注意,当这种情况发生时,结果是更准确的结果。中间舍入使误差略大于 ULP 的一半,而不是略小于 ULP 的一半。strtodstrtofdoublefloatstrtof(s, 0)(float)strtod(s, 0)doublefloatfloatstrtof

double在转换为之前经历双舍入问题的十进制表示的一个示例float1.01161128282547(取自此测验)。最近double的正好在两个floats 之间。直接四舍五入float得到你最近的float,并通过最近的double产生另一个float

于 2019-08-01T11:37:41.780 回答
0

无论您使用什么类型,x86 FPU 始终使用 80 位浮点数。double从 转换为甚至会产生额外的运行时成本float

我不确定,但strtof()可以实现为 wrapper around strtod(),所以我最好在你的地方使用strtof(),而不是调用函数来解析为 double 然后转换为float,以表明你的意图。如果您不信任编译器并且想要优化代码,那么使用 of 可能(float)strtod()会为您节省一些额外call/ret指令的性能。

于 2019-08-01T11:25:45.140 回答