【问题标题】:Why is `abs()` implemented differently?为什么 `abs()` 的实现方式不同?
【发布时间】:2019-09-18 20:30:29
【问题描述】:

在过去的几周里,我的代码中出现了一个非常令人沮丧的错误。我的代码可以在我的计算机上完全按预期运行,但是一旦我将其移植到 HPC 服务器,它就会产生奇怪的结果。

我将其归结为:在我的计算机 (iMac) 上,函数 abs() 使用浮点数,但在服务器上 abs() 将其截断为整数。

例子:

服务器

abs(-1.1341234) = 1

我的电脑

abs(-1.1341234) = 1.1341234

现在我知道我可以使用fabs() 来解决这个问题,这不是问题所在。我查看了两台机器上gcc 的版本,这是输出:

服务器

g++ -v
Using built-in specs.
COLLECT_GCC=g++
COLLECT_LTO_WRAPPER=/apps/software/GCCcore/5.4.0/libexec/gcc/x86_64-unknown-linux-gnu/5.4.0/lto-wrapper
Target: x86_64-unknown-linux-gnu
Configured with: ../configure --enable-languages=c,c++,fortran --enable-lto --enable-checking=release --disable-multilib --enable-shared=yes --enable-static=yes --enable-threads=posix --enable-gold=default --enable-plugins --enable-ld --with-plugin-ld=ld.gold --prefix=/apps/software/GCCcore/5.4.0 --with-local-prefix=/apps/software/GCCcore/5.4.0 --enable-bootstrap --with-isl=/dev/shm/GCCcore/5.4.0/dummy-/gcc-5.4.0/stage2_stuff
Thread model: posix
gcc version 5.4.0 (GCC) 

我的电脑

g++ -v
Configured with: --prefix=/Library/Developer/CommandLineTools/usr --with-gxx-include-dir=/Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk/usr/include/c++/4.2.1
Apple LLVM version 10.0.1 (clang-1001.0.46.3)
Target: x86_64-apple-darwin18.5.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin

所以我的问题是,为什么abs() 在 gcc 和 clang 之间产生不同的结果?这个问题确实花费了我 3 周的时间,所以你可以想象我刚才有点咸......

【问题讨论】:

  • 你可以想象我刚才有点咸…… 烦人但值得一讲……这会让你对这些事情非常敏感。 ;-)(我的意思不是这种冒犯性,而是一种“提醒”。每个真正令人讨厌的错误至少可能会产生宝贵的经验。所以,积极地接受它......)
  • @Scheff 哦,伙计,我当然不会忘记这一课......
  • @Scheff 好的编程语言不应该有这样的怪癖。 (这里还有要学习的一课,但我不知道是哪一课;-))
  • -Wall,修复所有警告。总是。

标签: c++ gcc compilation clang


【解决方案1】:

必须使用std::abs,它具有原始类型的重载。

在一种情况下,您正在使用 C++ 版本,在另一种情况下使用旧的 C 版本(将其参数转换为整数类型)。

要避免的事情:(1) using namespace std; (here is why) 和 (2) 没有适当的 #includes 来引入您需要的功能。 不要依赖 C++ 标准库实现为您隐式包含文件。

如果您适当地设置警告级别,一些编译器会警告您“有损”转换。

【讨论】:

  • @BenjaminBihler:这把罐子踢到了路上——例如 long double 的晶圆厂休息。
  • @BenjaminBihler 如果您使用的是 c++,通常没有充分的理由不使用 c++ 版本的函数。保持 C 到 C 和 C++ 到 C++。
  • 更正:使用 fabs 代替 absstd::abs 这是一个模板函数。
  • 所有编译器应该警告您浮点到整数或整数到浮点的转换。如果您的编译器没有,并且您无法相应地调整其警告级别,请立即丢弃它并让自己成为更好的编译器。
  • @Rakete1111:总的来说,这是有损的。例如。 64 位 int 和 IEEE754 double
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多