strtof(s, 0);
或者
(float)strtod(s, 0);
直观地说,这两种方法应该得到相同的结果,但是在所有情况下直觉是否正确呢?或者有没有一些边缘情况,第二种方法通过两次舍入与第一种方法略有不同的结果呢?
strtof(s, 0);
或者
(float)strtod(s, 0);
直观地说,这两种方法应该得到相同的结果,但是在所有情况下直觉是否正确呢?或者有没有一些边缘情况,第二种方法通过两次舍入与第一种方法略有不同的结果呢?
C标准对strtod
和strtof
的规范不够明确。它留下了可能性,即strtof
始终、很频繁或从不返回(float)strtod
。(本段引用了标准的另一部分,其中包含该段落,该段落指出“结果是最接近可表示值、或者是最接近最接近可表示值的较大或较小可表示值之一,以实现定义的方式选择”)。
typical 的 strtod
和 strtof
实现分别返回最接近传递给它们的十进制表示的 double
和最接近的 float
。当这些函数以这种方式运行时,那么 strtof(s, 0)
几乎总是与 (float)strtod(s, 0)
相同。它们不相同的十进制表示被称为 double-rounding problem,因为先将其四舍五入到 double
,再四舍五入到 float
,会产生与直接四舍五入到float
不同的结果。请注意,当发生这种情况时,strtof
的结果更加准确。中间舍入使错误略大于半个 ULP 而不是略小于半个 ULP。
在将数字从 double
转换为 float
时,出现双重舍入问题的十进制表示的一个例子是 1.01161128282547
(取自 这个测验)。最接近的 double
正好位于两个 float
之间。直接舍入到 float
可以得到最接近的 float
,而通过最接近的 double
则产生另一个 float
。
printf("%a\n", 1.01161128282547);
的输出结果为 0x1.02f8f5p+0
,这有助于说明“最接近的双精度浮点数恰好处于两个单精度浮点数之间的中间位置”。 - chux - Reinstate Monicax86 FPU 总是使用 80 位浮点数,无论您使用什么类型。甚至在从 double
转换为 float
时可能会有额外的运行时成本。
我不确定,但 strtof()
可以作为 strtod()
的包装器实现,因此在您的位置上,我最好使用 strtof()
,而不是调用函数进行解析为 double,然后强制转换为 float
,以表明您的意图。如果您不信任编译器并希望优化代码,则可能使用 (float)strtod()
可以节省一些额外的性能,减少 call/ret
指令。
float
,而应始终使用double
。 - Some programmer dudegcc -funsafe-math-optimizations ...
进行编译怎么办?(-ffast-math
设置了-funsafe-math-optimizations
等...) - Andrew Henleint x = 1 + 1;
设置x
为 2 吗?”你会认为没有办法确定未来的 C 编译器不会搞砸它吗?不会的,如果编译器没有将x
设置为 2,那么它就不是 C 编译器。(是的,gcc -ffast-math
不是 C 编译器,因为 GCC 的开发人员会第一个告诉你。) - Pascal Cuoq1 + 1
那样……),我认为对于那些对精确浮点结果感兴趣到发帖提问的人来说,应该考虑到这一点。 - Andrew Henle