在使用 IEEE-754 的不同 C++ 实现中,cos(x) 是否需要 return 相同的值?

Is cos(x) required to return identical values in different C++ implementations that use IEEE-754?

是否有任何形式的保证——无论是在 C++ 标准中还是在其他文档中——C++ 代码计算 cos(x) 在使用 g++、clang、MSVC 等编译时会产生相同的值,假设这些实现使用 IEEE-754 64 位 doubles 并且输入值 x 完全相等?我的假设是“是”,但我想在依赖此行为之前确认这一点。

上下文:我正在教授一门课程,学生可能需要在该课程中计算输入的三角函数。我可以保证这些输入在输入函数时是相同的。我知道相等性测试 doubles 不是一个好主意,但在这种特定情况下,我想知道这样做是否安全。

cos是超越函数。超越函数受制于table-制造者困境。通俗地说,这意味着:假设您提出了一些迭代算法来近似输入值的余弦值:例如,泰勒级数。当您 运行 这种迭代算法时,您必须决定在中间阶段保留多少额外精度(过早舍入可能会降低最终结果的准确性)。但是因为该函数是超越的,所以很难确定 在计算过程中必须携带多少额外位 才能产生正确舍入的最终结果,并且对于某些输入值,数字所需的额外位可能非常大。

出于这个原因,设计硬件来保证超越函数的正确舍入结果通常是不切实际的,例如 cos(其中“正确舍入”意味着得到的浮点数值是最接近函数真实值的值)。取而代之的是,硬件设计人员将实施一种性能相当不错的计算技术,对于 大多数 实际输入值,将产生与实际结果相差 1 位以内的结果。 (如果你绝对需要一个总是产生正确舍入结果的余弦函数,那么显然 可能 实现一个:GNU MPFR 声称已经做到了。但这比硬件性能差得多.)

IEEE 754 (2008) 将 cos 列为“推荐的正确舍入函数”之一,这意味着如果您实现 IEEE 754 版本的 cos,那么你必须产生一个正确舍入的结果。但这些功能只是“建议”提供,并非必需。因此,符合 IEEE 754 标准的实现可能无法提供正确舍入的 cos 函数,而是可能会提供“实用的”cos 函数,如上一段。因此,在实践中,两个声称符合 IEEE 754 标准的 C++ 实现在应用于相同参数时可能不会为诸如 cos 之类的超越函数产生完全相同的值。

(请注意,IEEE 754 要求 实现提供正确四舍五入的平方根函数。这不是超越函数,因此正确四舍五入并不难。 )