例如,用于32位IEEE浮点数的pow(浮点数,浮点数).如果传入相同的两个浮点数,则所有实现的结果是否相同?
或者是否有一些灵活性,标准允许根据用于实施战俘的算法的微小差异?
解决方法
也就是说,如果一个实现使用IEC 60559并定义__STDC_IEC_559__,那么它必须遵守C标准的附录F(是的,你的问题是关于C,但是C标准遵循C标准的C标准,如math.h ).附件F规定:
- The
float
type matches the IEC 60559 single format.- The
double
type matches the IEC 60559 double format.- The
long double
type matches an IEC 60559 extended format,else a
non-IEC 60559 extended format,else the IEC 60559double
format.
此外,它说正常算术必须遵循IEC 60559标准:
- The
+
,−
,*
,and/
operators provide the IEC 60559 add,subtract,multiply,and divide operations.
它还要求sqrt遵循IEC 60559:
- The
sqrt
functions in<math.h>
provide the IEC 60559 square root operation.
然后继续描述其他几个浮点函数的行为,其中大多数你可能对这个问题不感兴趣.
最后,它到达math.h标题,并指定各种数学函数(即sin,cos,atan2,exp等)应如何处理特殊情况(即asin(±0)返回±0,atanh(x)返回NaN并引发| x |> 1等的“无效”浮点异常.但它从来没有确定正常输入的精确计算,这意味着你不能依赖于产生完全相同计算的所有实现.
所以不,它不要求这些函数在所有实现中表现相同,即使这些实现都定义了__STDC_IEC_559__.
这都是从理论的角度来看的.在实践中,情况更糟. cpu通常实现IEC 60559算法,但是可以有不同的舍入模式(因此计算机的结果会有所不同),编译器(取决于优化标志)可能会做出一些不严格符合标准的假设.浮点运算.
所以在实践中,它甚至比理论上更严格,你很可能会看到两台计算机在某些时候产生的结果略有不同.
一个真实世界的例子是glibc,即GNU C库实现. They have a table of known error limits for their math functions跨越不同的cpu.如果所有C数学函数都是位精确的,那些表将显示0个错误的ULP.但他们没有.表格显示其C数学函数确实存在不同的误差量.我认为这句话是最有趣的总结:
Except for certain functions such as
sqrt
,fma
andrint
whose results are fully specified by reference to corresponding IEEE 754 floating-point operations,and conversions between strings and floating point,the GNU C Library does not aim for correctly rounded results for functions in the math library[…]
glibc中唯一具有精确位置的东西是C标准的附件F要求精确的东西.正如你在他们的表中所看到的,大多数事情都没有.