2010-06-25 16 views

risposta

105

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

In C, abs funziona solo su numeri interi e è necessario fabs per valori in virgola mobile. Questi sono disponibili in C++ (insieme a tutta la libreria C), ma non è necessario usarli.

+0

È questo su ogni piattaforma il caso? Esp. Windows e Mac OS X? O è almeno nello standard C++? – math

+2

@brubelsabs: sì. Non c'è bisogno di una funzione fabs separata in C++ poiché C++ ha un sovraccarico di funzione (abs può essere definito per numerosi tipi ed è in C++). È anche garantito dallo standard. Ovviamente se si scavalca qualche compilatore obsoleto di oltre 10 anni, si potrebbe trovare uno che non lo supporta. – stinky472

+1

È nello standard C++, quindi è il caso su ogni piattaforma con un compilatore decente, inclusi Windows e Mac OS X. La clausola 26.5 dice che, oltre alla versione 'int' dalla libreria C, ci sono sovraccarichi per' lungo ',' float', 'double' e' long double'. La clausola 26.2.7 definisce anche un sovraccarico per 'complex'. –

21

È ancora possibile utilizzare gli argomenti fabs per double e float. Lo preferisco perché garantisce che se accidentalmente spoglio lo std:: dello abs, il comportamento rimanga lo stesso per gli ingressi in virgola mobile.

Ho appena trascorso 10 minuti a eseguire il debug di questo problema, a causa del mio errore di utilizzare abs anziché std::abs. Supponevo che il using namespace std; avrebbe dedotto std::abs ma non lo fece, e invece stava usando la versione C.

In ogni caso, credo sia opportuno utilizzare fabs anziché abs per gli input a virgola mobile come un modo per documentare chiaramente l'intenzione.

+2

È strano. La tua chiamata avrebbe dovuto essere ambigua (e quindi un errore) giusto? – Nick

+0

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

+0

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

7

C'è ancora un motivo per raccomandare lo std::fabs per gli ingressi in virgola mobile in modo esplicito.

Se si dimentica di includere <cmath>, il tuo std::abs(my_float_num) può essere std::abs(int) invece 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'uso del template e specialmente quando si usa mpreal ci sono casi con messaggi "sovraccarichi ambigui" difficili - abs(static_cast<T>(x)) non risolve sempre questo. Quando gli addominali sono ambigui, ci sono possibilità che fabs stia funzionando come previsto. Per sqrt non ho trovato una fuga così semplice.

Da settimane faccio fatica a C++ "problemi non esistenti". Sto aggiornando un vecchio programma C++ in C++ 14 per un uso migliore e migliore del modello rispetto a prima possibile. Spesso lo stesso parametro del template può essere effettivo per qualsiasi tipo float standard o complesso o tipo di classe. Perché mai, il lungo doppio ha agito in qualche modo più sensibile di altri tipi. Tutto funzionava, e avevo incluso prima mpreal. Quindi stavo impostando il mio tipo di float predefinito su mpreal e ottenuto un diluvio di errori di sintassi. Che ha dato migliaia di sovraccarichi ambigui, ad es. per abs e sqrt, piangere per soluzioni diverse. Alcuni avevano bisogno di funzioni di aiuto sovraccariche, ma al di fuori di un modello. Dovuto sostituire singolarmente un migliaio di usi di 0.0L e 1.0L con il tipo esatto costante usando Zero o Uno o un tipo_cast - definizione di conversione automatica impossibile a causa di ambiguità.

Fino a maggio ho trovato molto interessante l'esistenza di conversioni implicite. Ma molto più semplice sarebbe senza, e avere costanti typeave con tipi_casts sicuri sicuri a qualsiasi altro tipo di costante standard.

Problemi correlati