web-dev-qa-db-fra.com

Quelles sont les valeurs min / max réelles pour float et double (C ++)

J'ai lu des recommandations pour utiliser les valeurs "FLT_MIN" et "FLT_MAX" pour float. Chaque fois que je fais cela, les blocs de code me disent

max: 3.40282e + 038 min: 1.17549e-038

Ne sachant pas ce que cela signifiait, j'ai essayé d'obtenir de vraies valeurs et

max: 47.2498237715 min: -34.8045265148

... mais cela ne clarifie pas les choses.

Voici un extrait de mon code

   char c;         // reserve: 1 byte, store 1 character (-128 to 127)
   int i;          // reserve: 4 bytes, store -2147483648 to 2147483657
   short int s;    // reserve: 2 bytes, store -32768 to 32767
   float f;        // reserve: 4 bytes, store ?? - ?? (? digits)
   double d;       // reserve: 8 bytes, store ?? - ?? (? digits)
   unsigned int u; //reserve: r bytes store 0 to 4294967295

   c = 'c';
   cout << c <<" lives at " << &c <<endl;

   i = 40000;
   cout << i <<" lives at " << &i <<endl;

   s = 100;
   cout << s <<" lives at " << &s <<endl;

   f = 10.1;
   cout << f <<" lives at " << &f <<endl;

   d = 10.102;
   cout << d <<" lives at " << &d <<endl;

   u = 1723;
   cout << u <<" lives at " << &u <<endl;

Dans l'extrait, nous pouvons clairement voir les valeurs min-max d'un short int, par exemple à -32768 - 32767. Ce sont des valeurs compréhensibles appropriées, mais pour float et int, les valeurs réelles ne sont pas claires.

5
user9318444

La classe std::numerics_limits Dans l'en-tête <limits> Fournit des informations sur les caractéristiques des types numériques.

Pour un type à virgule flottante T, voici les valeurs les plus grandes et les moins représentables dans le type, dans divers sens de "plus grand" et "moins". J'inclus également les valeurs du type binaire 64 bits IEEE 754 commun, appelé double dans cette réponse. Ce sont en ordre décroissant:

  • std::numeric_limits<T>::infinity() est la plus grande valeur représentable si T prend en charge l'infini. C'est, bien sûr, l'infini. La prise en charge de l'infini par le type T est indiquée par std::numeric_limits<T>::has_infinity.

  • std::numeric_limits<T>::max() est la plus grande valeur finie. Pour double, c'est 21024-2971, environ 1,79769 • 10308.

  • std::numeric_limits<T>::min() est la plus petite valeur normale positive. Les formats à virgule flottante ont souvent un intervalle où l'exposant ne peut pas devenir plus petit, mais la significande (partie fraction du nombre) est autorisée à devenir plus petite jusqu'à ce qu'elle atteigne zéro. Cela se fait au détriment de la précision, mais présente certaines propriétés souhaitables de calcul mathématique. min() est le point de départ de cette perte de précision. Pour double, c'est 2−1022, environ 2,22507 • 10−308.

  • std::numeric_limits<T>::denorm_min() est la plus petite valeur positive. Dans les types qui ont des valeurs sous-normales, elle est sous-normale. Sinon, il est égal à std::numeric_limits<T>::min(). Pour double, c'est 2−1074, environ 4,94066 • 10−324.

  • std::numeric_limits<T>::lowest() est la valeur la moins finie. Il s'agit généralement d'un nombre négatif de grande ampleur. Pour double, c'est - (21024-2971), environ −1,79769 • 10308.

  • Si std::numeric_limits<T>::has_infinity Et std::numeric_limits<T>::is_signed Sont vrais, alors -std::numeric_limits<T>::infinity() est la plus petite valeur. C'est, bien sûr, l'infini négatif.

Une autre caractéristique qui pourrait vous intéresser est:

  • std::numeric_limits<T>::digits10 Est le plus grand nombre de chiffres décimaux, de sorte que la conversion de n'importe quel nombre décimal avec autant de chiffres en T, puis la reconversion au même nombre de chiffres décimaux produira le nombre d'origine. Pour double, c'est 15.
4
Eric Postpischil

Tout se trouve dans numeric_limits.

Mais [~ # ~] méfiez-vous [~ # ~]

Pour une raison que je ne connais pas, std::numeric_limits<float>:min() ne retourne pas le flottant minimum. Au lieu de cela, il renvoie le plus petit flottant positif représenté sous une forme normalisée. Pour obtenir le minimum, utilisez std::numeric_limits<float>::lowest(). Je ne plaisante pas. De même pour les autres types à virgule flottante, c'est-à-dire double et long double.

http://en.cppreference.com/w/cpp/types/numeric_limits

4
Jive Dadson

Bien. En utilisant ce que j'ai appris d'ici (merci à tous) et les autres parties du Web, j'ai écrit un petit résumé des deux, au cas où je rencontrerais un autre problème comme celui-ci.

En C++, il existe deux façons de représenter/stocker des valeurs décimales.

Flotteurs et doubles

Un flotteur peut stocker des valeurs de:

  • -340282346638528859811704183484516925440.0000000000000000 Flotteur le plus bas
  • 340282346638528859811704183484516925440.0000000000000000 Float max

Un double peut stocker des valeurs de:

  • -179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368,0000000000000000 double le plus bas

  • 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368,0000000000000000 Double max

La précision de Float lui permet de stocker une valeur allant jusqu'à 9 chiffres (7 chiffres réels, +2 de la conversion décimale en binaire)

Double, comme son nom l'indique, peut stocker deux fois plus de cul que de flotteur. Il peut stocker jusqu'à 17 chiffres. (15 chiffres réels, +2 de la conversion décimale en binaire)

par exemple.

     float x = 1.426;
     double y = 8.739437;

Décimales et mathématiques

En raison d'un flotteur pouvant transporter 7 décimales réelles , et un double capable de porter 15 réels décimales, lors des calculs, les imprimer, une méthode appropriée doit être utilisée.

par exemple

comprendre

typedef std::numeric_limits<double> dbl; 
cout.precision(dbl::max_digits10-2); // sets the precision to the *proper* amount of digits.
cout << dbl::max_digits10 <<endl; // prints 17.
double x = 12345678.312; 
double a = 12345678.244; 
// these calculations won't perform correctly be printed correctly without setting the precision.


cout << endl << x+a <<endl;

exemple 2:

typedef std::numeric_limits< float> flt;
cout.precision(flt::max_digits10-2);
cout << flt::max_digits10 <<endl;
float x =  54.122111;
float a =  11.323111;

cout << endl << x+a <<endl; /* without setting precison this outputs a different value, as well as making sure we're *limited* to 7 digits. If we were to enter another digit before the decimal point, the digits on the right would be one less, as there can only be 7. Doubles work in the same way */

Quelle est la précision de cette description? Peut-il être utilisé comme standard lorsqu'il est condusé?

3
user9318444

En C++, vous pouvez utiliser le std::numeric_limits classe pour obtenir ce type d'informations.

Si has_infinity est true (ce qui est le cas pour pratiquement toutes les plateformes de nos jours), alors vous pouvez utiliser infinity pour obtenir la valeur qui est supérieure ou égale à toutes les autres valeurs (sauf NaN). Sa négation donnera un infini négatif, et sera inférieure ou égale à toutes les autres valeurs (sauf NaN à nouveau).

Si vous voulez des valeurs finies, vous pouvez utiliser max , qui sera supérieur ou égal à toutes les autres valeurs finies, et lowest =, qui est inférieur ou égal à toutes les autres valeurs finies.

Quelque peu confus, min vous donne en fait la plus petite valeur normalisée positive, qui est complètement désynchronisée avec ce qu'elle donne avec les types entiers (merci @JiveDadson de l'avoir signalé).

0
Simon Byrne