Когда я использую fabs и когда достаточно использовать std::abs?
Я предполагаю что abs
а также fabs
ведут себя по-разному при использовании math.h
, Но когда я использую только cmath
а также std::abs
я должен использовать std::fabs
или же fabs
? Или это не определено?
4 ответа
В C++ всегда достаточно использовать std::abs
; он перегружен для всех числовых типов.
В С, abs
работает только на целых числах, и вам нужно fabs
для значений с плавающей запятой. Они доступны в C++ (вместе со всей библиотекой C), но их не нужно использовать.
Это все еще в порядке, чтобы использовать fabs
за double
а также float
аргументы. Я предпочитаю это, потому что это гарантирует, что если я случайно лишу std::
от abs
, что поведение остается тем же для входных данных с плавающей запятой.
Я просто потратил 10 минут на отладку этой самой проблемы из-за моей собственной ошибки использования abs
вместо std::abs
, Я предположил, что using namespace std;
будет выводить std::abs
но это не так, а вместо этого использовал версию C.
Во всяком случае, я считаю, что это хорошо использовать fabs
вместо abs
для входных данных с плавающей точкой как способ документирования вашего намерения.
Есть еще одна причина, чтобы рекомендовать std::fabs
для входных данных с плавающей запятой явно.
Если вы забыли включить std::abs(my_float_num)
может быть std::abs(int)
вместо std::abs(float)
, Это трудно заметить.
"abs" и "fabs" идентичны только для типов с плавающей точкой C++, когда они могут быть переведены без неоднозначных сообщений о перегрузке.
Я использую g++ (g++-7). Вместе с использованием шаблонов и особенно при использовании mpreal существуют случаи с жесткими сообщениями "неоднозначной перегрузки" - abs(static_cast<T>(x))
не всегда решает это. Когда абс неоднозначен, есть вероятность, что потрясающая работа работает, как ожидалось. Для sqrt я не нашел такого простого побега.
Уже несколько недель я тяжело бьюсь над С ++ "несуществующими проблемами". Я обновляю старую программу C++ до C++14 для большего и лучшего использования шаблонов, чем раньше. Часто один и тот же параметр шаблона может быть действительным для любого стандартного типа с плавающей запятой или сложного типа или типа класса. Почему длинный двойной действовал несколько более разумно, чем другие типы. Все работало, и я включил mpreal раньше. Затем я установил тип плава по умолчанию mpreal и получил поток синтаксических ошибок. Это дало тысячи неоднозначных перегрузок, например, для abs и sqrt, которые требовали разных решений. Некоторым нужны были перегруженные справочные функции, но за пределами шаблона. Пришлось индивидуально заменить тысячу использований 0.0L и 1.0L точным типом константы с использованием Zero или One или type_cast - автоматическое определение преобразования невозможно из-за неясностей.
До мая я обнаружил, что существующие неявные преобразования очень хороши. Но гораздо проще было бы без них, и иметь константы сохранения типов с безопасными явными type_casts для любого другого стандартного константного типа.