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