¿Existe una forma estándar y / o portátil de representar el valor negativo más pequeño (por ejemplo, para usar infinito negativo) en un programa C (++)?
DBL_MIN en float.h es el número positivo más pequeño .
¿Existe una forma estándar y / o portátil de representar el valor negativo más pequeño (por ejemplo, para usar infinito negativo) en un programa C (++)?
DBL_MIN en float.h es el número positivo más pequeño .
Respuestas:
-DBL_MAX
en ANSI C , que se define en float.h.
-DBL_MAX
ser exactamente representable, por lo que si el hardware FP no es capaz de eso, la implementación simplemente tiene que solucionarlo. Consulte el modelo de punto flotante en 5.2.4.2.2 Características de los tipos flotantes <float.h> p2 de C99 (puede que se haya movido a otro lugar desde entonces).
DBL_MAX
es exactamente (1 - b ^ −p) b ^ e_max, que es exactamente representable, el valor finito más negativo es exactamente - (1 - b ^ −p) b ^ e_max, y dado que resulta ser exactamente -DBL_MAX
, la negación DBL_MAX
tampoco puede introducir errores de redondeo.
Los números de coma flotante (IEEE 754) son simétricos, por lo que si puede representar el mayor valor ( DBL_MAX
o numeric_limits<double>::max()
), simplemente anteponga un signo menos.
Y luego está la forma genial:
double f;
(*((long long*)&f))= ~(1LL<<52);
En C, use
#include <float.h>
const double lowest_double = -DBL_MAX;
En C ++ pre-11, use
#include <limits>
const double lowest_double = -std::numeric_limits<double>::max();
En C ++ 11 y posteriores, use
#include <limits>
constexpr double lowest_double = std::numeric_limits<double>::lowest();
min()
disponible la función antes de C ++ 11? ¿O es un valor diferente al -max()
? en.cppreference.com/w/cpp/types/numeric_limits
min
obtiene el valor positivo más pequeño en magnitud y lowest
el valor negativo más grande en magnitud. Sí, es terrible. Bienvenido al brillante mundo de la biblioteca estándar de C ++ :-P
.
float.h
. limits.h
es para enteros
Prueba esto:
-1 * numeric_limits<double>::max()
Referencia: numeric_limits
Esta clase está especializada para cada uno de los tipos fundamentales, y sus miembros regresan o establecen los diferentes valores que definen las propiedades que tiene ese tipo en la plataforma específica en la que compila.
-numeric_limits<double>::max()
?
-1 * ...
para aclarar un poco más.
¿Está buscando el infinito real o el valor finito mínimo? Si es el primero, use
-numeric_limits<double>::infinity()
que solo funciona si
numeric_limits<double>::has_infinity
De lo contrario, debe usar
numeric_limits<double>::lowest()
que se introdujo en C ++ 11.
Si lowest()
no está disponible, puede recurrir a
-numeric_limits<double>::max()
que puede diferir de lowest()
en principio, pero normalmente no lo hace en la práctica.
-numeric_limits<double>::max()
incluso si funciona en la práctica, no es completamente portátil en teoría.
A partir de C ++ 11 puedes usar numeric_limits<double>::lowest()
. Según el estándar, devuelve exactamente lo que está buscando:
Un valor finito x tal que no hay otro valor finito y donde
y < x
.
Significativo para todas las especializaciones en las queis_bounded != false
.
Hay muchas respuestas disponibles -std::numeric_limits<double>::max()
.
Afortunadamente, funcionarán bien en la mayoría de los casos. Los esquemas de codificación de coma flotante descomponen un número en una mantisa y un exponente y la mayoría de ellos (por ejemplo, el popular IEEE-754 ) utilizan un bit de signo distinto, que no pertenece a la mantisa. Esto permite transformar el positivo más grande en el negativo más pequeño simplemente volteando el signo:
El estándar no impone ningún estándar de punto flotante.
Estoy de acuerdo en que mi argumento es un poco teórico, pero supongamos que algún compilador excéntrico usaría un esquema de codificación revolucionario con una mantisa codificada en algunas variaciones del complemento a dos . La codificación del complemento a dos no es simétrica. por ejemplo, para un carácter de 8 bits con signo, el máximo positivo es 127, pero el mínimo negativo es -128. Entonces, podríamos imaginar que alguna codificación de punto flotante muestra un comportamiento asimétrico similar.
No conozco ningún esquema de codificación como ese, pero el punto es que el estándar no garantiza que el cambio de signo produzca el resultado deseado . Así que esta respuesta popular (¡lo siento chicos!) No puede considerarse como una solución estándar totalmente portátil. / * al menos no si no afirmas que numeric_limits<double>::is_iec559
es cierto * /
La pregunta original se refiere al infinito. Entonces, ¿por qué no usar
#define Infinity ((double)(42 / 0.0))
según la definición de IEEE? Puedes negar eso, por supuesto.
numeric_limits<double>::has_infinity && ! numeric_limits<double>::traps
¿Existe una forma estándar y / o portátil de representar el valor negativo más pequeño (por ejemplo, para usar infinito negativo) en un programa C (++)?
Enfoque C.
Muchas implementaciones admiten +/- infinitos, por lo que el double
valor más negativo es -INFINITY
.
#include <math.h>
double most_negative = -INFINITY;
¿Existe una forma estándar y / o portátil ....?
Ahora también debemos considerar otros casos:
Simplemente -DBL_MAX
.
Esperaría que en este caso, OP preferiría -DBL_MAX
.
DBL_MAX
.Este es un caso inusual, probablemente fuera de la preocupación de OP. Cuando double
se codifica como un par de puntos flotantes para lograr el rango / precesión deseado, (ver doble-doble ) existe un máximo normal double
y quizás uno mayor de lo normal . He visto debatir si DBL_MAX
debería referirse a la mayor normalidad , a la mayor de ambas.
Afortunadamente, este enfoque emparejado generalmente incluye un infinito, por lo que permanece el valor más negativo -INFINITY
.
Para una mayor portabilidad, el código puede seguir el camino
// 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;
Si no tiene habilitadas las excepciones flotantes (que no debería en mi humilde opinión), simplemente puede decir:
double neg_inf = -1/0.0;
Esto produce infinito negativo. Si necesita un flotador, puede lanzar el resultado
float neg_inf = (float)-1/0.0;
o utilizar aritmética de precisión simple
float neg_inf = -1.0f/0.0f;
El resultado es siempre el mismo, hay exactamente una representación de infinito negativo tanto en precisión simple como doble, y se convierten entre sí como era de esperar.
-INFINITY
neg_inf
se inicializa a un valor constante . El compilador se encargará de calcular el inf
valor. Y cuando lo usa como valor nulo para calcular un máximo, la primera iteración generalmente lo sobrescribirá con un valor mayor. Es decir, el rendimiento no es un problema. Y el OP pregunta específicamente sobre "por ejemplo, usar infinito negativo", y de -inf
hecho es la única respuesta correcta a esto. Ha votado en contra de una respuesta correcta y útil.