Existe uma maneira padrão e / ou portátil de representar o menor valor negativo (por exemplo, usar infinito negativo) em um programa C (++)?
DBL_MIN em float.h é o menor número positivo .
Existe uma maneira padrão e / ou portátil de representar o menor valor negativo (por exemplo, usar infinito negativo) em um programa C (++)?
DBL_MIN em float.h é o menor número positivo .
Respostas:
-DBL_MAX
em ANSI C , que é definido em float.h.
-DBL_MAX
ser exatamente representável, então se o hardware do FP não for capaz disso, a implementação precisa apenas contornar isso. Veja o modelo de ponto flutuante em 5.2.4.2.2 Características dos tipos flutuantes <float.h> p2 de C99 (pode ter sido movido para outro lugar desde então).
DBL_MAX
é exatamente (1 - b ^ −p) b ^ e_max, que é exatamente representável, o valor finito mais negativo é exatamente - (1 - b ^ −p) b ^ e_max, e como isso é exatamente -DBL_MAX
, negar DBL_MAX
também não pode introduzir erros de arredondamento.
Os números de ponto flutuante (IEEE 754) são simétricos, portanto, se você pode representar o maior valor ( DBL_MAX
ou numeric_limits<double>::max()
), apenas prefixe um sinal de menos.
E então é a maneira legal:
double f;
(*((long long*)&f))= ~(1LL<<52);
Em C, use
#include <float.h>
const double lowest_double = -DBL_MAX;
Em C ++ pré-11, use
#include <limits>
const double lowest_double = -std::numeric_limits<double>::max();
No C ++ 11 e posterior, use
#include <limits>
constexpr double lowest_double = std::numeric_limits<double>::lowest();
min()
função não estava disponível antes do C ++ 11? Ou isso é um valor diferente de -max()
? en.cppreference.com/w/cpp/types/numeric_limits
min
obtém o menor valor positivo em magnitude e lowest
o maior valor negativo em magnitude. Sim, é terrível. Bem-vindo ao mundo brilhante da biblioteca padrão C ++ :-P
.
float.h
. limits.h
é para números inteiros
Experimente isto:
-1 * numeric_limits<double>::max()
Referência: numeric_limits
Esta classe é especializada para cada um dos tipos fundamentais, com seus membros retornando ou configurados para os diferentes valores que definem as propriedades que o tipo possui na plataforma específica em que é compilado.
-numeric_limits<double>::max()
?
-1 * ...
para torná-lo um pouco mais claro.
Você está procurando o infinito real ou o valor finito mínimo? Se for o primeiro, use
-numeric_limits<double>::infinity()
que só funciona se
numeric_limits<double>::has_infinity
Caso contrário, você deve usar
numeric_limits<double>::lowest()
que foi introduzido no C ++ 11.
Se lowest()
não estiver disponível, você pode voltar para
-numeric_limits<double>::max()
que pode ser diferente lowest()
em princípio, mas normalmente não na prática.
-numeric_limits<double>::max()
mesmo que funcione na prática, não é totalmente portátil em teoria.
A partir do C ++ 11 você pode usar numeric_limits<double>::lowest()
. De acordo com o padrão, ele retorna exatamente o que você está procurando:
Um valor finito x tal que não existe outro valor finito y onde
y < x
.
Significativo para todas as especializações nas quaisis_bounded != false
.
Existem muitas respostas acontecendo -std::numeric_limits<double>::max()
.
Felizmente, eles funcionarão bem na maioria dos casos. Os esquemas de codificação de ponto flutuante decompõem um número em uma mantissa e um expoente e a maioria deles (por exemplo, o popular IEEE-754 ) usa um bit de sinal distinto, que não pertence à mantissa. Isso permite transformar o maior positivo no menor negativo apenas girando o sinal:
O padrão não impõe nenhum padrão de ponto flutuante.
Eu concordo que meu argumento é um pouco teórico, mas suponha que algum criador de compiladores excêntricos usaria um esquema de codificação revolucionário com uma mantissa codificada em algumas variações de um do complemento de dois . A codificação do complemento de dois não é simétrica. por exemplo, para um caractere de 8 bits com sinal, o máximo positivo é 127, mas o mínimo negativo é -128. Portanto, podemos imaginar que alguma codificação de ponto flutuante mostre um comportamento assimétrico semelhante.
Não estou ciente de nenhum esquema de codificação como esse, mas o ponto é que o padrão não garante que a inversão do sinal produza o resultado pretendido . Portanto, esta resposta popular (desculpe pessoal!) Não pode ser considerada uma solução padrão totalmente portátil! / * pelo menos não se você não afirmou que numeric_limits<double>::is_iec559
é verdade * /
A questão original diz respeito ao infinito. Então, por que não usar
#define Infinity ((double)(42 / 0.0))
de acordo com a definição do IEEE? Você pode negar isso, é claro.
numeric_limits<double>::has_infinity && ! numeric_limits<double>::traps
Existe uma maneira padrão e / ou portátil de representar o menor valor negativo (por exemplo, usar infinito negativo) em um programa C (++)?
Abordagem C.
Muitas implementações suportam +/- infinitos, então o double
valor mais negativo é -INFINITY
.
#include <math.h>
double most_negative = -INFINITY;
Existe uma forma padrão e / ou portátil ....?
Agora precisamos considerar também outros casos:
Simplesmente -DBL_MAX
.
Eu esperaria neste caso, OP preferiria -DBL_MAX
.
DBL_MAX
.Este é um caso incomum, provavelmente fora das preocupações da OP. Quando double
é codificado como um par de pontos flutuantes para atingir a faixa / precessão desejada, (ver duplo-duplo ) existe um máximo normal double
e talvez um maior anormal . Eu vi um debate se DBL_MAX
deveria se referir ao maior normal , ao maior de ambos.
Felizmente, essa abordagem emparelhada geralmente inclui um -infinity, de modo que o valor mais negativo permanece -INFINITY
.
Para maior portabilidade, o código pode seguir o caminho
// HUGE_VAL is designed to be infinity or DBL_MAX (when infinites are not implemented)
// .. yet is problematic with unsigned infinity.
double most_negative1 = -HUGE_VAL;
// Fairly portable, unless system does not understand "INF"
double most_negative2 = strtod("-INF", (char **) NULL);
// Pragmatic
double most_negative3 = strtod("-1.0e999999999", (char **) NULL);
// Somewhat time-consuming
double most_negative4 = pow(-DBL_MAX, 0xFFFF /* odd value */);
// My suggestion
double most_negative5 = (-DBL_MAX)*DBL_MAX;
Se você não tem exceções flutuantes habilitadas (o que você não deveria imho), você pode simplesmente dizer:
double neg_inf = -1/0.0;
Isso resulta em infinito negativo. Se você precisar de um float, você pode lançar o resultado
float neg_inf = (float)-1/0.0;
ou use aritmética de precisão única
float neg_inf = -1.0f/0.0f;
O resultado é sempre o mesmo, há exatamente uma representação de infinito negativo em precisão simples e dupla, e eles convertem um para o outro como você esperaria.
-INFINITY
neg_inf
é inicializado com um valor constante . O compilador cuidará de calcular o inf
valor. E quando você o usa como valor nulo para calcular um máximo, a primeira iteração geralmente o substitui por um valor maior. Ou seja, o desempenho dificilmente é um problema. E o OP pergunta especificamente sobre "por exemplo, usar infinito negativo", e -inf
é de fato a única resposta correta para isso. Você votou contra uma resposta correta e útil.