2009-12-27 8 views
9

ici est une question assez simple C++ (je pense), est-il une méthode de bibliothèque STL qui fournit la limite d'un type de variable(entier par exemple)? Je sais que ces limites diffèrent selon les ordinateurs, mais il doit y avoir un moyen de les faire passer par une méthode, n'est-ce pas?types de variables limite

Aussi, serait-il vraiment difficile d'écrire une méthode pour calculer la limite d'un type variable?

Je suis simplement curieux! :)

Merci;).

Répondre

35

Utilisation std::numeric_limits:

// numeric_limits example 
// from the page I linked 
#include <iostream> 
#include <limits> 
using namespace std; 

int main() { 
    cout << boolalpha; 
    cout << "Minimum value for int: " << numeric_limits<int>::min() << endl; 
    cout << "Maximum value for int: " << numeric_limits<int>::max() << endl; 
    cout << "int is signed: " << numeric_limits<int>::is_signed << endl; 
    cout << "Non-sign bits in int: " << numeric_limits<int>::digits << endl; 
    cout << "int has infinity: " << numeric_limits<int>::has_infinity << endl; 
    return 0; 
} 
4

(racontai à C, mais je pense que cela vaut aussi pour C++)

Vous pouvez également essayer "enquire", qui est un script qui peut recréer des limites .h pour votre compilateur. Une citation de la page d'accueil de l'projetc:

Ceci est un programme qui détermine beaucoup propriétés du compilateur C et machine qui est exécuté sur, comme minimum et maximum [un] signé char/int/long, de nombreuses propriétés de float/[long] double, et ainsi de suite. En option, il produit les fichiers ANSI C float.h et limits.h.

Comme une option supplémentaire, il vérifie même que le compilateur lit les fichiers d'en-tête correctement.

Il est un bon test cas pour les statisticiens, car il les exerce avec beaucoup de valeurs limites, telles que le minimum et maximum nombres à virgule flottante.

2
#include <limits> 

std::numeric_limits<type>::max() // min() etc 
12

Je vois que la réponse « correcte » a déjà été donné: Utilisez <limits> et laissez la magie se produire. Je trouve cette réponse insatisfaisante, puisque la question est:

Serait-il vraiment difficile d'écrire une méthode pour calculer la limite d'un type variable?

La réponse est: facile pour les types entiers, difficile pour les types float. Il y a 3 types d'algorithmes de base dont vous auriez besoin pour cela. Signé, non signé et virgule flottante. chacun a un algorithme différent pour la façon dont vous obtenez le min et le max, et le code réel implique un peu de twittling, et dans le cas de virgule flottante, vous devez boucler sauf si vous avez un type entier connu qui est la même taille que le float type.

Alors, c'est ici.

Non signé est facile. le min est quand tous les bits sont à 0, le maximum est quand tous les bits sont à 1.

const unsigned type unsigned_type_min = (unsigned type)0;  
const unsigned type unsigned_type_max = ~(unsigned type)0; 

Pour signé, le min est lorsque le bit de signe est défini, mais tous les autres bits sont des zéros, le maximum est quand tous les bits sauf le bit de signe sont fixés. Sans connaître la taille du type, nous ne savons pas où est le bit de signe, mais nous pouvons utiliser quelques astuces pour que cela fonctionne.

const signed type signed_type_max = (signed type)(unsigned_type_max >> 1); 
const signed type signed_type_min = (signed type)(~(signed_type_max)); 

pour virgule flottante, il existe des limites 4, bien que knowning seulement les limites positives est suffisante, les limites négatives sont simplement signer inversées limites positives. Il y a potentiellement plusieurs façons de représenter les nombres à virgule flottante, mais pour ceux qui utilisent un point à virgule binaire (plutôt que base 10), presque tout le monde utilise des représentations IEEE.

Pour les flottants IEEE, la plus petite valeur à virgule flottante positive est lorsque le bit le plus faible de l'exposant est 1 et tous les autres bits sont à 0. La plus grande valeur à virgule flottante négative est l'inverse au niveau du bit de ceci. Cependant, sans un type entier connu pour avoir la même taille que le type à virgule flottante donné, il n'y a aucun moyen de faire cette manipulation de bits autre que l'exécution d'une boucle. Si vous avez un type entier dont vous savez qu'il a la même taille que votre type virgule flottante, vous pouvez le faire en une seule opération.

const float_type get_float_type_smallest() { 
    const float_type float_1 = (float_type)1.0; 
    const float_type float_2 = (float_type)0.5; 
    union { 
     byte ab[sizeof(float_type)]; 
     float_type fl; 
     } u; 
    for (int ii = 0; ii < 0; ++ii) 
     u.ab[ii] = ((byte*)&float_1)[ii]^((byte*)&float_2)[ii]; 
    return u.fl; 
    } 

const float_type get_float_type_largest() { 
    union { 
     byte ab[sizeof(float_type)]; 
     float_type fl; 
     } u; 
    u.fl = get_float_type_smallest(); 
    for (int ii = 0; ii < 0; ++ii) 
     u.ab[ii] = ~u.ab[ii]; 
    return -u.fl; // Need to re-invert the sign bit. 
    } 
+0

Je pense que votre réponse est la plus informative, alors voici un upvote et mes salutations! –

+0

Vous assumez deux compliments sur les entiers, ce qui n'est pas nécessairement vrai. La seule façon portable d'obtenir la valeur maximale non signée est '= -1', ou certaines limites sont constantes. – GManNickG

+0

@GMan: Les systèmes qui ne font pas les maths compliment de deux sont théoriquement possibles, mais ils sont une curiosité historique, pas un véritable problème de portabilité. –