Почему 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++, чтобы неявно включать файлы для вас.
Некоторые компиляторы будут предупреждать вас о преобразовании с потерями, если вы установите соответствующий уровень предупреждения.