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