gpt4 book ai didi

c++ - asin 使用 Clang 在不同的平台上产生不同的答案

转载 作者:太空狗 更新时间:2023-10-29 20:08:17 26 4
gpt4 key购买 nike

#include <cmath>
#include <cstdio>

int main() {
float a = std::asin(-1.f);
printf("%.10f\n", a);
return 0;
}

我使用 clang、g++ 和 Visual Studio 在多个平台上运行了上面的代码。他们都给了我相同的答案:-1.5707963705

如果我在 macOS 上使用 clang 运行它,它会给我 -1.5707962513。macOS 上的 Clang 应该使用 libc++,但 macOS 是否有自己的 libc++ 实现?

如果我运行 clang --verison 我得到:

Apple LLVM version 10.0.0 (clang-1000.11.45.5)
Target: x86_64-apple-darwin18.0.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin

最佳答案

asinlibm 中实现,它是标准 C 库的一部分,而不是 C++ 标准库。 (从技术上讲,C++ 标准库包括 C 库函数,但实际上 Gnu 和 LLVM C++ 库的实现都依赖于底层平台数学库。)这三个平台——Linux、OS X 和 Windows——各有各的数学库的实现,因此如果正在使用库函数,它肯定可以是不同的库函数,并且结果可能在最后一位位置不同(这是您的测试显示的)。

但是,很可能库函数在所有情况下都不会被调用。这将取决于编译器和您传递给它们的优化选项(可能还有其他一些选项)。自 asin函数是标准库的一部分,因此具有已知行为,编译器计算 std::asin(-1.0F) 的值是完全合法的。在编译时,对于任何其他常量表达式(如 1.0 + 1.0 ,几乎所有编译器都会在编译时常量折叠为 2.0)。

由于您没有提到您使用的是什么优化设置,所以很难确切地说出发生了什么,但我用 http://gcc.godbolt.org 做了一些测试。获得基本概念:

  • GCC 常量折叠对 asin 的调用没有任何优化标志,但它不会预先计算 printf 中的参数提升(将 a 转换为 double 以便将其传递给 printf )除非您至少指定 -O1 . (使用 GCC 8.3 测试)。

  • Clang (7.0) 调用标准库函数,除非您至少指定 -O2 .但是,如果您显式调用 asinf , 它不断折叠在 -O1 .去图吧。

  • MSVC (v19.16) 不会持续折叠。它要么调用 std::asin包装器或直接调用 asinf ,取决于优化设置。我不太了解包装器的作用,也没有花太多时间进行调查。

GCC 和 Clang 常量都将表达式折叠为精确相同的二进制值(0xBFF921FB60000000 作为 double 值),即二进制值 -1.10010010000111111011011(尾随零被截断)。

注意 printf 之间也有区别三个平台上的实现(printf 也是平台 C 库的一部分)。理论上,您可以从相同的二进制值看到不同的十进制输出,但由于 printf 的参数被提升为double之前 printf被调用并且促销被精确定义并且不会改变值(value),这在这种特殊情况下极不可能产生任何影响。

作为旁注,如果您真的关心小数点后第七位,请使用 double而不是 float .事实上,你应该只使用 float在精度不重要的非常具体的应用中;正常的浮点类型是 double .

关于c++ - asin 使用 Clang 在不同的平台上产生不同的答案,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55245293/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com