标准对于std :: pow,std :: log等cmath函数有什么看法?

时间:2015-10-18 18:17:48

标签: c++ floating-point floating-accuracy ieee-754

标准是否保证函数在所有实现中返回完全相同的结果?

以32位IEEE浮点数为例pow(float,float)。如果传入相同的两个浮点数,则所有实现的结果是否相同?

或者,根据用于实现pow的算法,标准允许哪些微小差异?

1 个答案:

答案 0 :(得分:18)

不,C ++标准不要求cmath函数的结果在所有实现中都是相同的。对于初学者,您可能无法获得IEEE-754 / IEC 60559浮点运算。

那就是说,如果一个实现确实使用IEC 60559并定义__STDC_IEC_559__,那么必须遵守C标准的附件F(是的,你的问题是关于C ++,但是C ++标准遵循C标头的C标准,如math.h)。附件F指出:

  
      
  • float类型符合IEC 60559单一格式。
  •   
  • double类型符合IEC 60559双重格式。
  •   
  • long double类型符合IEC 60559扩展格式,否则为a   非IEC 60559扩展格式,否则为IEC 60559 double格式。
  •   

此外,它说正常算术必须遵循IEC 60559标准:

  
      
  • +*/运算符提供IEC 60559加,减,乘和除运算。
  •   

进一步要求sqrt遵循IEC 60559:

  
      
  • sqrt中的<math.h>函数提供IEC 60559平方根操作。
  •   

然后继续描述其他几个浮点函数的行为,其中大部分可能对此问题不感兴趣。

最后,它到达math.h标头,并指定各种数学函数的方式(即sincosatan2exp等。)应处理特殊情况(即asin(±0)返回±0atanh(x)返回NaN并引发| x |&gt; 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数学函数确实存在不同的误差量。我认为这句话是最有趣的总结:

  

除了某些函数,例如sqrtfmarint,其结果通过引用相应的IEEE 754浮点运算完全指定,以及字符串和浮点之间的转换, GNU C库的目标不是为数学库中的函数提供正确的舍入结果[...]

glibc中唯一具有位精确性的东西是C标准的附件F要求精确到位的东西。正如你在他们的表中所看到的,大多数事情都没有。