Quando uso fabs e quando è sufficiente utilizzare std :: abs?


100

Presumo che abse fabssi comportano in modo diverso durante l'utilizzo math.h. Ma quando uso solo cmathe std::abs, devo usare std::fabso fabs? O non è definito?

Risposte:


124

In C ++, è sempre sufficiente usare std::abs; è sovraccarico per tutti i tipi numerici.

In C, absfunziona solo su numeri interi e sono necessari fabsvalori in virgola mobile. Questi sono disponibili in C ++ (insieme a tutta la libreria C), ma non è necessario utilizzarli.


È così su ogni piattaforma? Esp. Windows e Mac OS X? O è almeno nello standard C ++?
matematica

3
@brubelsabs: sì. Non è necessaria una funzione fabs separata in C ++ poiché C ++ ha un sovraccarico di funzioni (abs può essere definito per numerosi tipi ed è in C ++). Inoltre è garantito dallo standard. Ovviamente se cerchi un compilatore obsoleto di oltre 10 anni, potresti trovarne uno che non lo supporta.
stinky472

1
E 'nel ++ standard C, quindi è il caso su ogni piattaforma con un compilatore decente, tra cui Windows e Mac OS X. La clausola 26.5 dice che, in aggiunta alla intversione della libreria C, ci sono sovraccarichi di long, float, doublee long double. La clausola 26.2.7 definisce anche un sovraccarico per complex.
Mike Seymour

6
Se dimentichi std::e lo usi abs, il tuo codice funzionerà come previsto su Windows ma utilizzerà la intversione su Linux, che può essere incredibilmente difficile da eseguire il debug.
Adversus

" tutti i tipi numerici" [citazione necessaria]. Posso vedere int, long, long long, std :: intmax_t, float, double, long double. Nessuna versione breve o char (o versioni non firmate) che posso vedere.
user673679

23

Va ancora bene usare fabsper doublee floatargomenti. Preferisco questo perché assicura che se spoglio accidentalmente std::il abs, il comportamento rimane lo stesso per gli input in virgola mobile.

Ho appena trascorso 10 minuti a eseguire il debug di questo stesso problema, a causa del mio errore di usare al absposto di std::abs. Ho pensato che using namespace std;avrebbe dedotto std::absma non l'ha fatto, e invece stava usando la versione C.

Ad ogni modo, credo che sia buono da usare al fabsposto degli absinput in virgola mobile come un modo per documentare chiaramente la tua intenzione.


2
Quello è strano. La tua chiamata avrebbe dovuto essere ambigua (e quindi un errore), giusto?
Nick

Non dovresti usare fabsf per float? Quindi non penso che siano identici.
Nick

Attenzione ad Android NDK g ++, cede anche alla funzione c abs () invece di std :: abs (). Nel compilatore Visual Studio c ++, tuttavia, abs punta sempre a std :: abs ().
sud

@ Nick, penso di essere d'accordo con te: non mi sembra di avere quel comportamento di Alan Turing, cioè per me il sovraccarico std::abssembra sempre essere invocato (e non la versione C di abs) quando si chiama absfintanto che using namespace std;è spiegato al inizio. Non so se questo sia specifico del compilatore.
MaviPranav

@ Nick non è un errore in quanto esiste un nome di funzione che corrisponde. È l'implementazione definita quale sarà scelta.
Pato Sandaña

11

C'è un motivo in più per raccomandare std::fabsesplicitamente gli input a virgola mobile.

Se dimentichi di includere <cmath>, std::abs(my_float_num)puoi essere al std::abs(int)posto di std::abs(float). È difficile da notare.


1

"abs" e "fabs" sono identici solo per i tipi float C ++, quando possono essere tradotti senza messaggi di sovraccarico ambigui.

Sto usando g ++ (g ++ - 7). Insieme all'utilizzo dei template e specialmente quando si usa mpreal ci sono casi con messaggi di "sovraccarico ambiguo" - abs(static_cast<T>(x))non è sempre risolutivo. Quando gli addominali sono ambigui, ci sono possibilità che fabs funzioni come previsto. Per sqrt non ho trovato una via di fuga così semplice.

Da settimane sto lottando duramente su C ++ "problemi non esistenti". Sto aggiornando un vecchio programma C ++ a C ++ 14 per un utilizzo migliore e migliore dei modelli rispetto a prima. Spesso lo stesso parametro del modello può essere effettivo qualsiasi tipo float standard o tipo complesso o un tipo di classe. Perché mai, il doppio lungo ha agito in modo un po 'più sensato di altri tipi. Tutto stava funzionando e prima avevo incluso mpreal. Quindi stavo impostando il mio tipo di float predefinito su mpreal e ho ricevuto un diluvio di errori di sintassi. Ciò ha dato migliaia di sovraccarichi ambigui, ad esempio per addominali e sqrt, chiedendo soluzioni diverse. Alcuni avevano bisogno di funzioni di aiuto sovraccariche, ma al di fuori di un modello. Ho dovuto sostituire individualmente mille utilizzi di 0,0L e 1,0L con il tipo di costante esatto utilizzando Zero o Uno o un type_cast - la definizione della conversione automatica impossibile a causa di ambiguità.

Fino a maggio ho trovato molto piacevole l'esistenza delle conversioni implicite. Ma sarebbe molto più semplice senza, e avere costanti typesave con type_cast espliciti sicuri su qualsiasi altro tipo di costante standard.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.