Presumo che abs
e fabs
si comportano in modo diverso durante l'utilizzo math.h
. Ma quando uso solo cmath
e std::abs
, devo usare std::fabs
o fabs
? O non è definito?
Presumo che abs
e fabs
si comportano in modo diverso durante l'utilizzo math.h
. Ma quando uso solo cmath
e std::abs
, devo usare std::fabs
o fabs
? O non è definito?
Risposte:
In C ++, è sempre sufficiente usare std::abs
; è sovraccarico per tutti i tipi numerici.
In C, abs
funziona solo su numeri interi e sono necessari fabs
valori in virgola mobile. Questi sono disponibili in C ++ (insieme a tutta la libreria C), ma non è necessario utilizzarli.
int
versione della libreria C, ci sono sovraccarichi di long
, float
, double
e long double
. La clausola 26.2.7 definisce anche un sovraccarico per complex
.
std::
e lo usi abs
, il tuo codice funzionerà come previsto su Windows ma utilizzerà la int
versione su Linux, che può essere incredibilmente difficile da eseguire il debug.
Va ancora bene usare fabs
per double
e float
argomenti. 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 abs
posto di std::abs
. Ho pensato che using namespace std;
avrebbe dedotto std::abs
ma non l'ha fatto, e invece stava usando la versione C.
Ad ogni modo, credo che sia buono da usare al fabs
posto degli abs
input in virgola mobile come un modo per documentare chiaramente la tua intenzione.
std::abs
sembra sempre essere invocato (e non la versione C di abs
) quando si chiama abs
fintanto che using namespace std;
è spiegato al inizio. Non so se questo sia specifico del compilatore.
C'è un motivo in più per raccomandare std::fabs
esplicitamente 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.
"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.