Presumo que abs
e fabs
estão se comportando de forma diferente ao usar math.h
. Mas quando uso apenas cmath
e std::abs
, devo usar std::fabs
ou fabs
? Ou isso não está definido?
Presumo que abs
e fabs
estão se comportando de forma diferente ao usar math.h
. Mas quando uso apenas cmath
e std::abs
, devo usar std::fabs
ou fabs
? Ou isso não está definido?
Respostas:
Em C ++, é sempre suficiente usar std::abs
; ele está sobrecarregado para todos os tipos numéricos.
Em C, abs
só funciona com inteiros e você precisa fabs
de valores de ponto flutuante. Eles estão disponíveis em C ++ (junto com toda a biblioteca C), mas não há necessidade de usá-los.
int
versão da biblioteca C, há sobrecargas para long
, float
, double
e long double
. A cláusula 26.2.7 também define uma sobrecarga para complex
.
std::
e apenas usar abs
, seu código funcionará como esperado no windows, mas usará a int
versão no linux, o que pode ser incrivelmente difícil de depurar.
Ainda não há problema em usar fabs
para double
e float
argumentos. Eu prefiro isso porque garante que, se eu acidentalmente remover std::
o abs
, que o comportamento permanecerá o mesmo para entradas de ponto flutuante.
Acabei de passar 10 minutos depurando esse problema, devido ao meu próprio erro de usar em abs
vez de std::abs
. Presumi que o using namespace std;
iria inferir, std::abs
mas isso não aconteceu e, em vez disso, estava usando a versão C.
De qualquer forma, acredito que seja bom usar em fabs
vez de abs
entradas de ponto flutuante como uma forma de documentar claramente sua intenção.
std::abs
sempre parece ser invocado (e não a versão C de abs
) ao chamar abs
, desde que using namespace std;
esteja explicado no começando. Não sei se isso é específico do compilador.
Há mais um motivo para recomendar std::fabs
explicitamente entradas de ponto flutuante.
Se você esquecer de incluir <cmath>, seu std::abs(my_float_num)
pode ser em std::abs(int)
vez de std::abs(float)
. É difícil perceber.
"abs" e "fabs" são idênticos apenas para tipos de float C ++, quando podem ser traduzidos sem mensagens de sobrecarga ambíguas.
Estou usando o g ++ (g ++ - 7). Junto com o uso do template e especialmente ao usar o mpreal, há casos com mensagens de "sobrecarga ambígua" - abs(static_cast<T>(x))
nem sempre resolvendo isso. Quando o abdômen é ambíguo, há chances de que os fabs estejam funcionando conforme o esperado. Para sqrt, não encontrei um escape tão simples.
Há semanas estou lutando arduamente em C ++ "problemas não existentes". Estou atualizando um programa C ++ antigo para C ++ 14 para obter mais e melhor uso de modelos do que antes. Freqüentemente, o mesmo parâmetro de modelo pode ser real qualquer tipo float padrão ou complexo ou um tipo de classe. Por que razão, long double agiu de forma um pouco mais sensata do que outros tipos. Tudo estava funcionando, e eu havia incluído a refeição antes. Então, eu estava configurando meu tipo de float padrão para mpreal e recebi um dilúvio de erros de sintaxe. Isso gerou milhares de sobrecargas ambíguas, por exemplo, para abdominais e sqrt, clamando por soluções diferentes. Alguns precisavam de funções de ajuda sobrecarregadas, mas fora de um modelo. Tive que substituir individualmente mil utilizações de 0,0L e 1,0L pelo tipo de constante exata usando Zero ou Um ou um type_cast - definição de conversão automática impossível devido às ambigüidades.
Até maio achei muito legal a existência de conversões implícitas. Mas muito mais simples seria sem nenhum, e ter constantes typesave com type_casts explícitos seguros para qualquer outro tipo de constante padrão.