繁体   English   中英

Clang和Visual C++之间的acos精度略有差异

[英]Slight acos precision difference between Clang and Visual C++

我有一些我正在使用的跨平台代码。 在 Mac 上使用 Clang 编译,在 Windows 上使用 Visual C++ 编译。

有一个计算可能很敏感,Mac 和触发断言的 Windows 之间存在差异。 最终 acos 结果之间存在差异,但我不清楚为什么。

在这两个平台上,acos 的输入正好是 -1.0f。 在 Visual C++ 中, acos(-1.0f)为 3.14159274。 这就是 pi 作为浮点数的值,这是我所期望的。

但在 macOS 上:

float value = acos(-1.0f);

...计算为 3.1415925。 这足以触发代码中的问题的准确性差异。 acos 是一种使用浮点数可能不精确的操作 - 我明白这一点。 而且不同的编译器可以有不同的acos实现。 我只是不清楚为什么 Clang 似乎对如此简单的 acos 结果有问题,而 Visual C++ 没有。 浮点数能够表示 3.14159274,但这不是我得到的结果。

可以从 Xcode 的 Clang 版本中获得准确/可视的 C++ 对齐值:

float value = (float)acos((double)-1.0f);

所以我可以通过提高精度来解决这个问题,然后将值向下转换为浮点数以保持与 Windows 相同的舍入。 我只是在寻找一个理由,说明当 VC++ 编译器似乎没有精度问题时,为什么需要额外的精度。 也可能是 Clang/Xcode/VC++ 数学库之间的差异。 我只是假设 acos(-1.0) 可能在编译器中更稳定。 我找不到舍入模式的任何差异(即使不需要舍入),并且 Xcode 和 Visual Studio 中的新项目显示出相同的差异。 两台机器都是英特尔的。

如果您查看这些浮点值的二进制表示,您可以看到 mac/clang 的值A是比 windows/msvc 的值B的下一个最低浮点数

A    3.14159250    0x40490FDA
B    3.14159274    0x40490FDB

虽然 B 最接近 π 的真实值,但它实际上大于 π,正如 @njuffa 在他们的评论中指出的那样。

阅读规范,看起来acosf应该返回一个封闭范围 [0,π] 内的值。 从技术上讲A符合此标准,而B不符合。

总之 -

  • A是最接近但小于 π 的值
  • B是最接近 π 的值

这些差异可能是各个标准库实现者深思熟虑的结果。

我还观察到这两个值都是cosf的真正倒数,因为cosf(A)cosf(B)都等于-1.0f

不过,一般来说,在任何浮点计算中依赖精确的位级精度是不明智的。 如果您还没有意识到这一点,文档What Every Computer Scientist Should Know About Floating-Point Arithmetic解释了原因。


编辑:我很好奇,在这里找到了相关的 Apple 源代码。

 Return value: ... Otherwise: ... Returns a value in [0, pi] (C 7.12.4.1 3). Note that this prohibits returning a correctly rounded value for acosf(-1), since pi rounded to a float lies outside that interval.

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM