Kiedy używam fabs, a kiedy wystarczy użyć std :: abs?

100

Zakładam to absi fabszachowuję się inaczej podczas używania math.h. Ale kiedy używam just cmathi std::abs, czy muszę używać std::fabslub fabs? Czy nie jest to zdefiniowane?

matematyka
źródło

Odpowiedzi:

124

W C ++ zawsze wystarczy użyć std::abs; jest przeciążony dla wszystkich typów liczbowych.

W C absdziała tylko na liczbach całkowitych i potrzebujesz fabswartości zmiennoprzecinkowych. Są one dostępne w C ++ (wraz z całą biblioteką C), ale nie ma potrzeby ich używania.

Mike Seymour
źródło
Czy tak jest na każdej platformie? Esp. Windows i Mac OS X? A może przynajmniej w standardzie C ++?
matematyka
3
@brubelsabs: tak. Nie ma potrzeby stosowania oddzielnej funkcji fabs w C ++, ponieważ C ++ ma przeciążenie funkcji (abs można zdefiniować dla wielu typów i jest w C ++). Gwarantuje to również norma. Oczywiście, jeśli poszukasz jakiegoś przestarzałego kompilatora starszego niż 10 lat, możesz znaleźć taki, który go nie obsługuje.
stinky472
1
Jest w C ++ standard, więc jest to sprawa na każdej platformie z godnej kompilatora, w tym Windows i Mac OS X. Klauzuli 26.5 mówi, że oprócz intwersji z biblioteki C, istnieje przeciążenia dla long, float, doublei long double. Punkt 26.2.7 definiuje również przeciążenie dla complex.
Mike Seymour
6
Jeśli zapomnisz std::i po prostu go użyjesz abs, twój kod będzie działał zgodnie z oczekiwaniami w systemie Windows, ale będzie używał intwersji pod Linuksem, co może być niezwykle trudne do debugowania.
Adversus
wszystkie typy liczbowe” [potrzebne źródło]. Widzę int, long, long long, std :: intmax_t, float, double, long double. Nie widzę wersji krótkich lub w postaci znaków (lub wersji bez znaku).
user673679
23

Nadal można używać argumentów fabsfor doublei float. Wolę to, ponieważ zapewnia to, że jeśli przypadkowo usunę std::element abs, zachowanie pozostanie takie samo dla danych zmiennoprzecinkowych.

Właśnie spędziłem 10 minut na debugowaniu tego właśnie problemu, z powodu mojego własnego błędu użycia abszamiast std::abs. Zakładałem, using namespace std;że wywnioskuje, std::absale tak się nie stało i zamiast tego użyłem wersji C.

W każdym razie uważam, że warto używać fabszamiast abszmiennoprzecinkowych danych wejściowych, aby jasno udokumentować swój zamiar.

Alan Turing
źródło
2
To jest dziwne. Twoje wezwanie powinno być niejednoznaczne (a tym samym błąd), prawda?
Nick
Nie powinieneś używać fabsf do float? Więc nie sądzę, żeby były identyczne.
Nick
Uważaj na Androida NDK g ++, ceduje on również funkcję c abs () zamiast std :: abs (). Jednak w kompilatorze Visual Studio C ++ abs zawsze wskazuje na std :: abs ().
Southerton
@Nick, myślę, że zgadzam się z tobą: wydaje mi się, że nie rozumiem tego zachowania Alana Turinga, tj. Dla mnie przeciążenie std::abszawsze wydaje się być wywoływane (a nie wersja C abs) podczas dzwonienia, abso ile using namespace std;jest to wyjaśnione w początek. Nie wiem, czy jest to specyficzne dla kompilatora.
MaviPranav
@Nick nie jest błędem, ponieważ istnieje nazwa funkcji, która pasuje. Jest to implementacja określona, ​​która z nich zostanie wybrana.
Pato Sandaña
11

Jest jeszcze jeden powód, dla którego warto std::fabsjawnie zalecać wprowadzanie danych zmiennoprzecinkowych.

Jeśli zapomnisz dołączyć <cmath>, std::abs(my_float_num)możesz std::abs(int)zamiast std::abs(float). Trudno to zauważyć.

Kenichi Hidai
źródło
1

„abs” i „fabs” są identyczne tylko dla typów zmiennoprzecinkowych C ++, gdy można je przetłumaczyć bez niejednoznacznych komunikatów o przeciążeniu.

Używam g ++ (g ++ - 7). Wraz z użyciem szablonu, a zwłaszcza przy używaniu mpreal, istnieją przypadki z twardymi komunikatami „niejednoznacznego przeciążenia” -abs(static_cast<T>(x)) nie zawsze to rozwiązuje. Kiedy abs jest niejednoznaczny, są szanse, że fabs działa zgodnie z oczekiwaniami. W przypadku sqrt nie znalazłem takiej prostej ucieczki.

Od tygodni ciężko zmagam się z „nieistniejącymi problemami” w C ++. Aktualizuję stary program C ++ do C ++ 14, aby korzystać z szablonów w większym i lepszym stopniu niż było to możliwe wcześniej. Często ten sam parametr szablonu może być w rzeczywistości dowolnym standardowym typem zmiennoprzecinkowym, typem złożonym lub typem klasy. Dlaczego zawsze, długi podwójny akt był nieco rozsądniejszy niż inne typy. Wszystko działało, a wcześniej włączyłem mpreal. Potem ustawiałem domyślny typ float na mpreal i dostałem zalew błędów składniowych. To dało tysiące niejednoznacznych przeciążeń, np. Dla abs i sqrt, wzywając do różnych rozwiązań. Niektórzy potrzebowali przeciążonych funkcji pomocy, ale poza szablonem. Trzeba było pojedynczo zastąpić tysiące zastosowań 0,0L i 1,0L dokładnym typem stałym przy użyciu Zero lub One lub type_cast - automatyczna definicja konwersji niemożliwa z powodu niejednoznaczności.

Do maja bardzo fajnie wydawało mi się istnienie niejawnych konwersji. Ale o wiele prościej byłoby bez żadnych i mieć typozapisywać stałe z bezpiecznymi jawnymi typami typu_cast do dowolnego innego standardowego typu stałego.

BS3
źródło