Коли я використовую файли і коли достатньо використовувати std :: abs?


100

Я припускаю, що absі fabsповодяться по-різному під час використання math.h. Але коли я користуюсь просто cmathта std::abs, чи повинен я використовувати std::fabsабо fabs? Або це не визначено?

Відповіді:


124

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

У C absпрацює лише ціла кількість, і вам потрібно fabsдля значень з плаваючою точкою. Вони доступні в C ++ (разом із усією бібліотекою С), але використовувати їх не потрібно.


Це так на кожній платформі? Esp Windows та Mac OS X? Або це принаймні в стандарті C ++?
математика

3
@brubelsabs: так. Немає необхідності в окремій функції файлів у C ++, оскільки C ++ має функцію перевантаження (abs можна визначити для численних типів і це в C ++). Це також гарантується стандартом. Звичайно, якщо розкопати знайти застарілий компілятор старше 10 років, ви можете знайти той, який не підтримує його.
stinky472

1
Це в стандарті C ++, так що це справа на кожній платформі з пристойним компілятором, включаючи Windows , і Mac OS X. Пунктом 26.5 говорить , що, на додаток до intверсії з бібліотеки C, є перевантажені для long, float, doubleі long double. Пункт 26.2.7 також визначає перевантаження для complex.
Майк Сеймур

6
Якщо ви забудете std::та просто користуєтесь abs, ваш код буде працювати, як очікувалося, на Windows, але він буде використовувати intверсію на Linux, яку неможливо важко налагодити.
Adversus

" усі числові типи" [потрібне цитування]. Я бачу int, long, long long, std :: intmax_t, float, double, long double. Немає коротких чи знакових версій (або неподписаних версій), які я бачу.
користувач673679

23

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

Щойно я витратив на налагодження цю саму проблему 10 хвилин через мою власну помилку використання absзамість цього std::abs. Я припускав, що using namespace std;буде std::absзроблено висновок, але цього не було, і натомість використовував версію C.

У будь-якому випадку, я вважаю, що це добре використовувати fabsзамість absвходів з плаваючою комою як спосіб чіткого документування свого наміру.


2
Це дивно. Ваш дзвінок повинен був бути неоднозначним (і, отже, помилкою), правда?
Нік

Чи не слід використовувати fabsf для float? Тому я не думаю, що вони однакові.
Нік

Остерігайтеся Android NDK g ++, він також передає функцію c abs () замість std :: abs (). Однак у компіляторі Visual Studio c ++ abs завжди вказує на std :: abs ().
southerton

@ Nick, я думаю, що я з вами згоден: я не маю на увазі, що така поведінка Алана Тьюрінга, тобто для мене перезавантажений std::absзавжди, як видається, викликається (а не C-версіями abs) під час виклику до absтих пір, поки using namespace std;це пояснюється на початок. Я не знаю, чи це конкретний компілятор.
MaviPranav

@Nick не є помилкою, оскільки є ім'я функції, яке відповідає. Саме реалізація визначає, який з них буде обраний.
Пато Санданья

11

Є ще одна причина рекомендувати std::fabsявно вводити з плаваючою комою.

Якщо ви забудете включити <cmath>, std::abs(my_float_num)можна std::abs(int)замість цього std::abs(float). Це важко помітити.


1

"abs" і "fabs" ідентичні лише для плавких типів C ++, коли їх можна перекладати без неоднозначних повідомлень про перевантаження.

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

З тижнів я важко борюся над C ++ "не існуючими проблемами". Я оновлюю стару програму C ++ до C ++ 14 для більшого та кращого використання шаблонів, ніж це можливо раніше. Часто один і той же параметр шаблону може бути фактичним для будь-якого стандартного поплавця або складного типу або типу класу. Чому колись довгі подвійні діяли дещо розумнішими, ніж інші типи. Все працювало, і я раніше включав mpreal. Тоді я встановлював мій тип float за замовчуванням mpreal і отримував помилки синтаксису. Це дало тисячі неоднозначних перевантажень, наприклад, для abs та sqrt, плачу за різними рішеннями. Деякі потребували перевантажених довідкових функцій, але поза шаблоном. Довелося індивідуально замінювати тисячу звичань 0,0L та 1,0L на точний постійний тип, використовуючи Zero або One або type_cast - визначення автоматичного перетворення неможливе через неоднозначності.

До травня я вважав, що наявна неявна конверсія є дуже приємною. Але набагато простіше було б без будь-якого і мати тип-збереження констант із безпечними явними type_casts до будь-якого іншого стандартного постійного типу.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.