Почему abs() реализован по-другому?

За последние несколько недель в моем коде была супер расстраивающая ошибка. Мой код будет работать точно так, как ожидалось, на моем компьютере, но как только я отправлю его на сервер 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 недели прогресса, так что, как вы можете себе представить, я сейчас немного соленая...

Ответы

Ответ 1

Вы должны использовать std::abs, который имеет перегрузки для примитивных типов.

В одном случае вы переходите на версию C++, а в другом - на старую версию C (которая преобразует свои параметры в целочисленные типы).

Что следует избегать: (1) using namespace std; (вот почему) и (2) отсутствие соответствующего #include для #include нужной вам функциональности. Не полагайтесь на стандартные реализации библиотеки C++, чтобы неявно включать файлы для вас.

Некоторые компиляторы будут предупреждать вас о преобразовании с потерями, если вы установите соответствующий уровень предупреждения.