Когда я использую 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 для любого другого стандартного константного типа.

Другие вопросы по тегам