Подтвердить что ты не робот

Когда я использую fabs и когда достаточно использовать std:: abs?

Я полагаю, что abs и fabs ведут себя разные при использовании math.h. Но когда я использую только cmath и std::abs, мне нужно использовать std::fabs или fabs? Или это не определено?

4b9b3361

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