Question

Je souhaite trouver le nombre de chiffres de mantisse et le nombre d'unités sur un ordinateur particulier. Je comprends ce qu’il en est, mais je ne sais absolument pas comment les trouver - bien que je sache qu’elles peuvent varier d’un ordinateur à l’autre.

J'ai besoin de ce numéro pour effectuer certains aspects de l'analyse numérique, comme l'analyse des erreurs.

Ce que je pense actuellement, c'est que je pourrais écrire un petit programme c ++ pour incrémenter lentement un nombre jusqu'à ce qu'il y ait débordement, mais je ne suis pas sûr du type de nombre à utiliser.

Suis-je sur la bonne voie? Comment fait-on exactement pour calculer cela?

Était-ce utile?

La solution

Je pense que quelle que soit la langue que vous utilisiez, vous spécifieriez comment les flottants étaient stockés. Je sais que Java le fait en utilisant un standard IEEE spécifique (754, je pense).

Si ce n’est pas spécifié, je pense que vous pourriez faire votre propre vérification en ajoutant 0,5 à 1 pour voir si le nombre réel change. Si tel est le cas, ajoutez 0,25 à 1, 0,125 à 1, et ainsi de suite jusqu'à ce que le nombre ne change pas, par exemple:

float a = 1;
float b = 0.5;
int bits = 0;
while (a + b != a) {
    bits = bits + 1;
    b = b / 2;
}

Si vous n'aviez que 3 bits de mantisse, 1 + 1/16 serait égal à 1.

Ensuite, vous avez épuisé vos bouts de mantisse.

Vous aurez peut-être besoin que le numéro de base soit 2 plutôt que 1, car IEEE754 utilise un "1+" implicite au début.

EDIT:

Il semble que la méthode décrite ci-dessus présente certains problèmes, car elle donne 63 bits pour un système disposant clairement de flottants de 4 octets.

Qu'il s'agisse de résultats intermédiaires (j'en doute, le même code avec des conversions explicites [while (((float)(a + b) != (float)(a))] présentant des problèmes similaires) ou (plus probablement, je crois) de la possibilité que la valeur d'unité a puisse être représentée avec des bits plus proches de la fraction b en ajustant l'exposant, je ne sais pas encore.

Pour le moment, il est préférable de s'appuyer sur les informations linguistiques mentionnées ci-dessus, telles que l'utilisation de IEEE754 (si ces informations sont disponibles).

Je laisserai le code problématique comme un piège pour les joueurs méfiants. Peut-être que quelqu'un avec plus de connaissances en virgule flottante pourra laisser une note expliquant pourquoi cela agit étrangement (aucune conjecture, s'il vous plaît: -).

EDIT 2:

Ce code corrige le problème en s'assurant que les intermédiaires sont stockés dans des flotteurs. Jonathan Leffler avait raison, c’était des résultats intermédiaires.

#include <stdio.h>
#include <float.h>

int main(void) {
    float a = 1;
    float b = 0.5;
    float c = a + b;
    int bits = 1;
    while (c != a) {
        bits = bits + 1;
        b = b / 2;
        c = a + b;
    }
    printf("%d\n",FLT_MANT_DIG);
    printf("%d\n",bits);
    return 0;

}

Ce code renvoie (24,24) pour indiquer que la valeur calculée correspond à celle du fichier d'en-tête.

Bien qu'écrit en C, il devrait être applicable à toutes les langues (en particulier aux langues dans lesquelles les informations ne sont pas disponibles dans un en-tête ou qui sont spécifiées dans la documentation de la langue). J'ai seulement testé en C parce qu'Eclipse met tellement de temps à démarrer sur ma machine Ubuntu: -).

Autres conseils

Pour C et par extension C ++, les informations sont dans les en-têtes <float.h> ou <cfloat>.

Pour C99, les informations figurent dans la section 5.2.4.2.2 de la norme:

  • FLT_RADIX
  • FLT_MANT_DIG
  • FLT_DIG
  • FLT_EPSILON
  • FLT_MIN_EXP
  • FLT_MIN
  • FLT_MIN_10_EXP
  • FLT_MAX_EXP
  • FLT_MAX
  • FLT_MAX_10_EXP

Et de même pour les variantes DBL et LDBL de la plupart d'entre elles (pas de DBL_RADIX ni de LDBL_RADIX). La norme suggère des valeurs appropriées pour IEEE 754 (l'ancienne version de la norme IEEE 754 en vigueur en 1999; une nouvelle version a été publiée dans, je crois, 2008).

Vous pouvez vérifier <limits> dans votre bibliothèque C ++:

#include <iostream>
#include <limits>
#include <typeinfo>

template <typename T>
void printDetailsFor() {
    std::cout
        << "Printing details for " << typeid(T).name() << ":\n"
        << "\tradix:        " << std::numeric_limits<T>::radix        << "\n"
        << "\tradix digits: " << std::numeric_limits<T>::digits       << "\n"
        << "\tepsilon:      " << std::numeric_limits<T>::epsilon()    << "\n"
        << std::endl;
}

int main() {
    printDetailsFor<int>();
    printDetailsFor<float>();
    printDetailsFor<double>();
    printDetailsFor<long double>();
    return 0;
}

Je pense que vous voulez std::numeric_limits<T>::digits ce qui devrait être un de plus que le nombre de bits de mantisse. Ma machine imprime:

Printing details for i:
    radix:        2
    radix digits: 31
    epsilon:      0

Printing details for f:
    radix:        2
    radix digits: 24
    epsilon:      1.19209e-07

Printing details for d:
    radix:        2
    radix digits: 53
    epsilon:      2.22045e-16

Printing details for e:
    radix:        2
    radix digits: 64
    epsilon:      1.0842e-19
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top