假设您有一个像“0.1”这样的字符串,它只能近似地表示为二进制浮点数,并且您想将其转换为单精度浮点数。这可以做到
strtof(s, 0);
或者
(float)strtod(s, 0);
从直觉上讲,这些应该给出相同的结果,但是直觉在所有情况下都是正确的吗?还是在某些边缘情况下,第二种形式经过两次舍入后得出的结果与第一种形式略有不同?
最佳答案
C标准的strtod
和strtof
规范未指定。这为strtof
始终,非常频繁或从不返回(float)strtod
留下了空间。 (This paragraph指的是包含that paragraph的标准的另一部分,其中说:“结果是以实现定义的方式选择的最接近的可表示值,或者紧邻最接近的可表示值的较大或较小的可表示值”)。strtod
和strtof
的典型实现分别将最接近的double
和最接近的float
返回到传递给它们的十进制表示形式。当这些函数以这种方式运行时,strtof(s, 0)
的几乎总是与(float)strtod(s, 0)
相同。十进制表示形式不一致的十进制表示形式表示为double-rounding problem,因为首先将十进制表示形式四舍五入到double
然后再四舍五入到float
会产生与直接四舍五入到float
不同的结果。请注意,发生这种情况时,strtof
结果是更精确的结果。中间舍入使误差略大于ULP的一半,而不是略小于ULP的一半。
在转换为double
之前通过float
时,带有双舍入问题的十进制表示形式的一个示例是1.01161128282547
(取自this quiz)。最近的double
恰好位于两个float
之间。直接舍入到float
会得到最接近的float
,而经过最接近的double
则会产生另一个float
。