web-dev-qa-db-fra.com

Quelle est la longueur maximale en caractères nécessaire pour représenter une valeur double?

Lorsque je convertis un entier de 8 bits non signé en chaîne, je sais que le résultat sera toujours au maximum de 3 caractères (pour 255) et pour un entier de 8 bits signé, nous avons besoin de 4 caractères, par exemple. "-128".

Maintenant, ce que je me demande en réalité est la même chose pour les valeurs à virgule flottante. Quel est le nombre maximal de caractères requis pour représenter une valeur "double" ou "float" sous forme de chaîne?

Supposons une expansion décimale double (IEEE 754) C/C++ normale (c'est-à-dire aucun formatage% e printf).

Je ne suis même pas sûr que le très petit nombre (0,234234) sera plus long que le très grand nombre (doubles représentant des entiers)?

44
martin

L'en-tête standard <float.h> en C, ou <cfloat> en C++, contient plusieurs constantes à faire avec la plage et d'autres métriques des types à virgule flottante. L'un d'entre eux est DBL_MAX_10_EXP, le plus grand exposant de puissance 10 requise pour représenter toutes les valeurs double. Puisque 1eN a besoin de N+1 chiffres à représenter et qu'il peut également y avoir un signe négatif, la réponse est

int max_digits = DBL_MAX_10_EXP + 2;

Cela suppose que l'exposant est plus grand que le nombre de chiffres requis pour représenter la plus grande valeur de mantisse possible; sinon, il y aura aussi un point décimal suivi de plus de chiffres.

CORRECTION

Le nombre le plus long est en fait le plus petit nombre négatif représentable: il doit contenir suffisamment de chiffres pour couvrir à la fois l'exposant et la mantisse. Cette valeur est -pow(2, DBL_MIN_EXP - DBL_MANT_Dig), où DBL_MIN_EXP est négatif. Il est assez facile de voir (et de prouver par induction) que -pow(2,-N) a besoin de 3+N caractères pour une représentation décimale non scientifique ("-0.", suivi de N chiffres). Donc la réponse est

int max_digits = 3 + DBL_MANT_Dig - DBL_MIN_EXP

Pour un double IEEE 64 bits, nous avons

DBL_MANT_Dig = 53
DBL_MIN_EXP = -1023
max_digits = 3 + 53 - (-1023) = 1079
34
Mike Seymour

Selon IEEE 754-1985, la notation la plus longue pour la valeur représentée par un type double, c'est-à-dire:

-2.2250738585072020E − 308

a 24 caractères.

13

Vous pouvez utiliser snprintf() pour vérifier le nombre de caractères dont vous avez besoin .snprintf() renvoie le nombre de caractères nécessaires pour imprimer tout ce qui lui est transmis.

/* NOT TESTED */
#include <stdio.h>
#include <stdlib.h>
int main(void) {
    char dummy[1];
    double value = 42.000042; /* or anything else */
    int siz;
    char *representation;
    siz = snprintf(dummy, sizeof dummy, "%f", value);
    printf("exact length needed to represent 'value' "
           "(without the '\\0' terminator) is %d.\n", siz);
    representation = malloc(siz + 1);
    if (representation) {
        sprintf(representation, "%f", value);
        /* use `representation` */
        free(representation);
    } else {
        /* no memory */
    }
    return 0;
}

Note: snprintf() est une fonction C99. Si un compilateur C89 le fournit en tant qu’extension, il risque de ne pas répondre aux attentes du programme ci-dessus.

Edit: Le lien en snprintf() a été remplacé par un lien décrivant réellement les fonctionnalités imposées par la norme C99; la description dans le lien d'origine est fausse.
2013: Le lien retour vers le site POSIX que je préfère par rapport au site de la première modification _.

4
pmg

Vous pouvez contrôler le nombre de chiffres dans la représentation sous forme de chaîne lorsque vous convertissez le type float/double en chaîne en définissant la précision. Le nombre maximal de chiffres serait alors égal à la représentation sous forme de chaîne de std::numeric_limits<double>::max() à la précision que vous spécifiez.

#include <iostream>
#include <limits>
#include <sstream>
#include <iomanip>

int main()
{
 double x = std::numeric_limits<double>::max();

 std::stringstream ss;
 ss << std::setprecision(10) << std::fixed << x;

 std::string double_as_string = ss.str();
 std::cout << double_as_string.length() << std::endl;
}

Ainsi, le plus grand nombre de chiffres d'une double avec une précision de 10 est 320 chiffres.

2
Charles Salvia

Une source d’information correcte et plus détaillée que la Spécification IEEE-754 sont ces notes de cours de UC Berkely page 4, plus quelques calculs improvisés. Ces diapositives de conférence sont également bonnes pour les étudiants en génie.

Tailles de tampon recommandées

| Single| Double | Extended | Quad  |
|:-----:|:------:|:--------:|:-----:|
|   16  |  24    |    30    |  45   |

Ces chiffres sont basés sur les calculs suivants:

Nombre décimal maximum de la portion intégrale

| Single| Double | Extended | Quad  |
|:-----:|:------:|:--------:|:-----:|
|   9   |   17   |    21    |  36   |

* Quantities listed in decimals.

Les décimales sont basées sur la formule: Au plus plafond (1 + N Log_10 (2)) décimales, où N est le nombre de bits de la partie intégrale *.

Longueur maximale des exposants

| Single| Double | Extended | Quad  |
|:-----:|:------:|:--------:|:-----:|
|   5   |   5    |     7    |   7   |
* Standard format is `e-123`.

L'algorithme le plus rapide

L’algorithme le plus rapide pour l’impression de nombres à virgule flottante est l’algorithme Grisu2 détaillé dans le document de recherche Impression rapide et précise de nombres à virgule flottante . Le meilleur repère que j'ai pu trouver peut être trouvé ici .

2
user2356685

1024 n'est pas suffisant, la plus petite valeur double négative a 1077 chiffres décimaux. Voici du code Java.

double x = Double.longBitsToDouble(0x8000000000000001L);
BigDecimal bd = new BigDecimal(x);
String s = bd.toPlainString();
System.out.println(s.length());
System.out.println(s);

Voici la sortie du programme.

1077
-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004940656458412465441765687928682213723650598026143247644255856825006755072702087518652998363616359923797965646954457177309266567103559397963987747960107818781263007131903114045278458171678489821036887186360569987307230500063874091535649843873124733972731696151400317153853980741262385655911710266585566867681870395603106249319452715914924553293054565444011274801297099995419319894090804165633245247571478690147267801593552386115501348035264934720193790268107107491703332226844753335720832431936092382893458368060106011506169809753078342277318329247904982524730776375927247874656084778203734469699533647017972677717585125660551199131504891101451037862738167250955837389733598993664809941164205702637090279242767544565229087538682506419718265533447265625
1
Fred

Cela dépend de ce que vous entendez par "représenter". La fraction décimale n'a pas de représentation exacte en virgule flottante. Lorsque vous convertissez une fraction décimale -> fraction binaire -> décimale, vous n’avez pas de représentation décimale exacte et vous aurez des bits de bruit à la fin de la représentation binaire.

La question n'impliquait pas de commencer à partir de décimal, mais tout le code source (et doit être saisi par l'utilisateur) est décimal et implique le problème de troncature possible. Que signifie "exact" dans ces circonstances?

En gros, cela dépend de votre représentation en virgule flottante.

Si vous avez 48 bits de mantisse, cela prend environ 16 chiffres décimaux. L'exposant pourrait être les 14 bits restants (environ 5 chiffres décimaux).

En règle générale, le nombre de bits est environ 3 fois le nombre de chiffres décimaux.

1
S.Lott

"Quelle est la longueur maximale en caractères nécessaire pour représenter une valeur double?"

La réponse exacte à cette question est la suivante: 8 caractères ASCII - dans un format hexadicimal, à l'exclusion du préfixe '0x' - exactitude de 100% :) (mais ce n'est pas qu'une blague)

La précision utilisable de la norme IEEE-754 double est d’environ 16 décimales - excluant ainsi les fins pédagogiques, les représentations plus longues ne représentent qu’un gaspillage de ressources et de puissance de calcul:

  • Les utilisateurs ne sont pas plus informés lorsqu'ils voient un numéro à 700 chiffres à l'écran.

  • Les variables de configuration stockées sous cette forme "plus précise" sont inutiles - chaque opération effectuée sur un tel nombre détruira la précision. (sans changer le bit de signe)

Si quelqu'un a besoin d'une meilleure précision real, il existe un double long de 80 bits avec une précision d'environ 18 chiffres ou f.e. libquadmath.

Cordialement.

1
vtomazzi

Le nombre maximal de caractères requis pour imprimer une valeur décimale double (c'est-à-dire au format "%f") correspond à la valeur de -DBL_MIN (c'est-à-dire -0x1p-1022, en supposant que binary64 IEEE 754 est votre double). Pour cela, vous aurez besoin d’exactement 325 caractères. C'est: DBL_Dig + abs(DBL_MIN_10_EXP) + strlen("-0."). Ceci est bien sûr parce que log10(fabs(DBL_MIN)) est égal à 308, ce qui est également abs(DBL_MIN_10_EXP)+1 (le +1 correspond au premier chiffre à gauche de la décimale) et correspond au nombre de zéros à gauche à gauche des chiffres significatifs.

int lz;                 /* aka abs(DBL_MIN_10_EXP)+1 */
int dplaces;
int sigdig;             /* aka DBL_DECIMAL_Dig - 1 */
double dbl = -DBL_MIN;

lz = abs((int) lrint(floor(log10(fabs(dbl)))));
sigdig = lrint(ceil(DBL_MANT_Dig * log10((double) FLT_RADIX)));
dplaces = sigdig + lz - 1;
printf("f = %.*f\n", dplaces, dbl);
0
Greg A. Woods

Ce n'est pas du tout un ensemble de réponses ambiguës. Je cherche quelque chose à dire à un spécificateur de format C # afin d’exercer un analyseur syntaxique sur lequel je travaille. Je génère de manière aléatoire certains cas de test, y compris des constantes de précision double ou à virgule flottante, et j'ai besoin de préserver l'aller-retour. Oui, je sais qu'il y a "aller-retour", c'est un aspect. Mais j'ai aussi besoin de supporter Fixé ainsi que Scientifique notation. Jusqu'ici, j'aime bien 1079 mais cela me semble excessif. Ou à tout le moins, ma comparaison "assez étroite" doit prendre en compte cette variance dans la vérification avant/après l'analyse.

0
mwpowellhtx