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

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

Ответы [ 4 ]

120 голосов
/ 25 июня 2010

В C ++ всегда достаточно использовать std::abs;он перегружен для всех числовых типов.

В C abs работает только с целыми числами, и вам нужно fabs для значений с плавающей запятой.Они доступны в C ++ (вместе со всей библиотекой C), но их не нужно использовать.

22 голосов
/ 10 декабря 2012

Все еще можно использовать fabs для double и float аргументов.Я предпочитаю это, потому что это гарантирует, что если я случайно уберу std:: с abs, то поведение останется таким же для входов с плавающей запятой.

Я просто потратил 10 минут на отладку этой самой проблемы из-заМоя собственная ошибка использования abs вместо std::abs.Я предполагал, что using namespace std; выведет std::abs, но это не так, и вместо этого я использовал версию C.

В любом случае, я считаю, что было бы хорошо использовать fabs вместо abs для плавающегоуказывать вводные данные как способ четко документировать ваше намерение.

9 голосов
/ 14 июля 2016

Есть еще одна причина явно рекомендовать std::fabs для входных данных с плавающей запятой.

Если вы забудете включить , ваш std::abs(my_float_num) может быть std::abs(int) вместо std::abs(float). Это трудно заметить.

1 голос
/ 14 июля 2017

«abs» и «fabs» идентичны только для типов с плавающей запятой C ++, когда они могут быть переведены без неоднозначных сообщений о перегрузке.

Я использую g ++ (g ++ - 7).Вместе с использованием шаблонов и особенно при использовании mpreal существуют случаи с жесткими сообщениями «неоднозначной перегрузки» - abs(static_cast<T>(x)) не всегда решает это.Когда абс неоднозначен, есть вероятность, что потрясающая работа работает, как ожидалось.Для sqrt я не нашел такого простого побега.

Уже несколько недель я тяжело бьюсь над C ++ "не существует проблем".Я обновляю старую программу C ++ до C ++ 14 для большего и лучшего использования шаблонов, чем раньше.Часто один и тот же параметр шаблона может быть действительным для любого стандартного типа с плавающей запятой или сложного типа или типа класса.Почему длинный двойной действовал несколько более разумно, чем другие типы.Все работало, и я включил mpreal раньше.Затем я установил тип плава по умолчанию mpreal и получил поток синтаксических ошибок.Это дало тысячи неоднозначных перегрузок, например, для abs и sqrt, которые требовали разных решений.Некоторым нужны были перегруженные справочные функции, но за пределами шаблона.Пришлось индивидуально заменить тысячу использований 0.0L и 1.0L точным типом константы с использованием Zero или One или type_cast - автоматическое определение преобразования невозможно из-за неоднозначностей.очень хорошо.Но гораздо проще было бы без них, и иметь константы сохранения типов с безопасными явными type_casts для любого другого стандартного константного типа.

...