Existe-t-il un moyen standard et / ou portable de représenter la plus petite valeur négative (par exemple pour utiliser l'infini négatif) dans un programme C (++)?
DBL_MIN dans float.h est le plus petit positif nombre .
Existe-t-il un moyen standard et / ou portable de représenter la plus petite valeur négative (par exemple pour utiliser l'infini négatif) dans un programme C (++)?
DBL_MIN dans float.h est le plus petit positif nombre .
Réponses:
-DBL_MAX
dans ANSI C , qui est défini dans float.h.
-DBL_MAX
d'être exactement représentable, donc si le matériel FP n'est pas capable de cela, l'implémentation doit juste contourner cela. Voir le modèle à virgule flottante en 5.2.4.2.2 Caractéristiques des types flottants <float.h> p2 de C99 (peuvent avoir été déplacés ailleurs depuis).
DBL_MAX
est exactement de (1 - b ^ −p) b ^ e_max, qui est exactement représentable, la valeur finie la plus négative est exactement - (1 - b ^ −p) b ^ e_max, et comme cela se trouve être exactement -DBL_MAX
, la négation DBL_MAX
ne peut pas non plus introduire d'erreurs d'arrondi.
Les nombres à virgule flottante (IEEE 754) sont symétriques, donc si vous pouvez représenter la plus grande valeur ( DBL_MAX
ounumeric_limits<double>::max()
), ajoutez simplement un signe moins.
Et puis est la manière cool:
double f;
(*((long long*)&f))= ~(1LL<<52);
En C, utilisez
#include <float.h>
const double lowest_double = -DBL_MAX;
Dans C ++ pré-11, utilisez
#include <limits>
const double lowest_double = -std::numeric_limits<double>::max();
Dans C ++ 11 et versions ultérieures, utilisez
#include <limits>
constexpr double lowest_double = std::numeric_limits<double>::lowest();
min()
fonction n'était-elle pas disponible avant C ++ 11? Ou est-ce une valeur différente de celle -max()
? en.cppreference.com/w/cpp/types/numeric_limits
min
vous obtenez la plus petite valeur positive en magnitude et lowest
la plus grande valeur négative en magnitude. Oui, c'est terrible. Bienvenue dans le monde brillant de la bibliothèque standard C ++ :-P
.
float.h
. limits.h
est pour les entiers
Essaye ça:
-1 * numeric_limits<double>::max()
Référence: numeric_limits
Cette classe est spécialisée pour chacun des types fondamentaux, ses membres retournant ou définis sur les différentes valeurs qui définissent les propriétés de ce type dans la plate-forme spécifique dans laquelle il se compile.
-numeric_limits<double>::max()
?
-1 * ...
pour le rendre un peu plus clair.
Recherchez-vous l'infini réel ou la valeur finie minimale? Si le premier, utilisez
-numeric_limits<double>::infinity()
qui ne fonctionne que si
numeric_limits<double>::has_infinity
Sinon, vous devez utiliser
numeric_limits<double>::lowest()
qui a été introduit dans C ++ 11.
S'il lowest()
n'est pas disponible, vous pouvez revenir à
-numeric_limits<double>::max()
ce qui peut différer du lowest()
principe, mais ne le fait normalement pas dans la pratique.
-numeric_limits<double>::max()
même si cela fonctionne dans la pratique, ce n'est pas entièrement portable en théorie.
À partir de C ++ 11, vous pouvez utiliser numeric_limits<double>::lowest()
. Selon la norme, il renvoie exactement ce que vous recherchez:
Une valeur finie x telle qu'il n'y a pas d'autre valeur finie y où
y < x
.
Significatif pour toutes les spécialisations dans lesquellesis_bounded != false
.
Il existe de nombreuses réponses pour -std::numeric_limits<double>::max()
.
Heureusement, ils fonctionneront bien dans la plupart des cas. Les schémas d'encodage en virgule flottante décomposent un nombre en une mantisse et un exposant et la plupart d'entre eux (par exemple le populaire IEEE-754 ) utilisent un bit de signe distinct, qui n'appartient pas à la mantisse. Cela permet de transformer le plus grand positif en le plus petit négatif en retournant simplement le signe:
La norme n'impose aucune norme à virgule flottante.
Je conviens que mon argument est un peu théorique, mais supposons qu'un fabricant de compilateur excentrique utilise un schéma de codage révolutionnaire avec une mantisse codée dans certaines variations d'un complément à deux . Le codage du complément à deux n'est pas symétrique. par exemple pour un caractère 8 bits signé, le maximum positif est 127, mais le minimum négatif est -128. Nous pourrions donc imaginer qu'un codage en virgule flottante montre un comportement asymétrique similaire.
Je ne connais aucun schéma d'encodage comme celui-là, mais le fait est que la norme ne garantit pas que le retournement de signe donne le résultat attendu . Donc, cette réponse populaire (désolé les gars!) Ne peut pas être considérée comme une solution standard entièrement portable! / * du moins pas si vous n'avez pas affirmé que numeric_limits<double>::is_iec559
c'est vrai * /
La question initiale concerne l'infini. Alors, pourquoi ne pas utiliser
#define Infinity ((double)(42 / 0.0))
selon la définition IEEE? Vous pouvez bien sûr nier cela.
numeric_limits<double>::has_infinity && ! numeric_limits<double>::traps
Existe-t-il un moyen standard et / ou portable de représenter la plus petite valeur négative (par exemple pour utiliser l'infini négatif) dans un programme C (++)?
Approche C.
De nombreuses implémentations prennent en charge +/- infinis, donc la double
valeur la plus négative est -INFINITY
.
#include <math.h>
double most_negative = -INFINITY;
Existe-t-il un moyen standard et / ou portable ...?
Maintenant, nous devons également considérer d'autres cas:
Simplement -DBL_MAX
.
Je m'attendrais dans ce cas, OP préférerait -DBL_MAX
.
DBL_MAX
.Il s'agit d'un cas inhabituel, probablement hors des préoccupations d'OP. Quand double
est codé comme une paire de points flottants pour atteindre la plage / précession désirée (voir double-double ), il existe une normale maximale double
et peut-être une plus grande dé-normale . J'ai vu un débat pour DBL_MAX
savoir s'il fallait se référer à la plus grande normale , à la plus grande des deux.
Heureusement, cette approche par paires inclut généralement un -infinity, donc la valeur la plus négative reste -INFINITY
.
Pour plus de portabilité, le code peut suivre la voie
// 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 vous n'avez pas activé les exceptions float (ce que vous ne devriez pas à mon humble avis), vous pouvez simplement dire:
double neg_inf = -1/0.0;
Cela donne une infinité négative. Si vous avez besoin d'un flotteur, vous pouvez soit lancer le résultat
float neg_inf = (float)-1/0.0;
ou utilisez l'arithmétique simple précision
float neg_inf = -1.0f/0.0f;
Le résultat est toujours le même, il y a exactement une représentation de l'infini négatif à la fois en simple et en double précision, et ils se convertissent l'un à l'autre comme vous vous en doutez.
-INFINITY
neg_inf
est initialisé à une valeur constante . Le compilateur se chargera de calculer la inf
valeur. Et lorsque vous l'utilisez comme valeur nulle pour calculer un maximum, la première itération l'écrasera généralement avec une valeur plus grande. Ie la performance n'est guère un problème. Et l'OP demande spécifiquement "par exemple utiliser l'infini négatif", et -inf
c'est en effet la seule réponse correcte à cela. Vous avez décliné une réponse correcte et utile.