2013-07-27 7 views
0
  • Plate-forme: Linux 3.2.0 (Debian 7.0)
  • compilateur: GCC 4.7.2 (Debian 4.7.2-5)

Je suis en train de convertir des chaînes de caractères dans flotteurs . Je suis conscient qu'il existe déjà des fonctions qui font cela. Je fais seulement cela pour la pratique. Ma fonction fonctionne bien avec des nombres simples comme 123.123, 1234, -678.8. Mais quand j'essaye de convertir la chaîne .99999999 en flotteur je me retrouve avec 1. Ce qui est évidemment un problème. Je ne sais pas si c'est parce que .99999999 ne peut pas être exprimé par un flotteur ou si je fais quelque chose de mal. La question que je pose est comment puis-je calculer la fraction maximale qu'un flotteur peut exprimer. Comment puis-je, faute d'un meilleur terme, savoir quand un flotteur est sur le point de déborder?Max Float Fraction

Voici ce que j'ai jusqu'à présent.

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

int cstrtof(const char *cstr, float *f); 
int cstrtof(const char *cstr, float *f) 
{ 
unsigned short int i = 0; 
unsigned short int bool_fraction = 0; 
float tmp_f = 0; 

if(cstr[0] == '\000') return -1; 
else if(cstr[0] == '-') i = 1; 

for(; cstr[i] != '\000'; i++) 
{ 
    printf("tmp_f = %f\n", tmp_f); 
    if(cstr[i] >= '0' && cstr[i] <= '9') 
    { 
     if(tmp_f > (FLT_MAX - (cstr[i] - '0'))/10) return -2; 
     else tmp_f = tmp_f * 10 + (cstr[i] - '0'); 
    } 
    else if(cstr[i] == '.') bool_fraction = i+1; 
    else return i+1; 
} 

printf("tmp_f = %f\nbool_fraction = %i\n", tmp_f, bool_fraction); 

if(bool_fraction) 
{ 
    for(bool_fraction--; bool_fraction < i-1; bool_fraction++, tmp_f /= 10) 
    { 
     printf("tmp_f = %f\n", tmp_f); 
    } 
} 

printf("tmp_f = %f\nbool_fraction = %i\n", tmp_f, bool_fraction); 

if(cstr[0] == '-') *f = tmp_f*-1; 
else *f = tmp_f; 

return 0; 
} 

int main(int argc, char *argv[]) 
{ 
float f = 0; 
int return_value = 0; 

return_value = cstrtof(argv[1], &f); 
if(return_value == 0) 
{ 
    printf("f = %.11f\n", f); 
} 
else if(return_value == -1) 
{ 
    printf("ERROR Empty String\n"); 
} 
else if(return_value == -2) 
{ 
    printf("ERROR Data Type Overflow\n"); 
} 
else 
{ 
    printf("ERROR Invalid character '%c'\n", argv[1][return_value-1]); 
} 

return 0; 
} 

De même cstrtof() est basé sur la fonction suivante.

int cstrtoslli(const char *cstr, signed long long int *slli) 
{ 
unsigned short int i = 0; 
signed long long int tmp_slli = 0; 

if(cstr[0] == '\000') return -1; 
else if(cstr[0] == '-') i = 1; 
else if(cstr[0] == '0') return -2; 

for(; cstr[i] != '\000'; i++) 
{ 
    if(cstr[i] >= '0' && cstr[i] <= '9') 
    { 
       //LLONG_MAX is defined in limits.h 
     if(tmp_slli > (LLONG_MAX - (cstr[i] - '0'))/10) return -3; 
     else tmp_slli = tmp_slli * 10 + (cstr[i] - '0'); 
    } 
    else return i+1; 
} 

if(cstr[0] == '-') *slli = tmp_slli*-1; 
else *slli = tmp_slli; 

return 0; 
} 
+0

"Je suis conscient qu'il existe déjà des fonctions qui font cela" -> Avez-vous envisagé d'utiliser ces fonctions comme référence? Il est plus rapide d'écrire 'strtof (". 99999999 ", ...)' que de poser une question sur StackOverflow. –

Répondre

2

représentable le plus float valeur inférieure à 1 est renvoyé par nexttowardf(1, -INFINITY).

Ceci aura généralement une fraction différente de celle, par exemple, la plus grande valeur représentable float inférieure à 2, qui est nexttowardf(2, -INFINITY). En effet, les nombres de grandeurs différentes ont généralement des nombres de bits différents pour la partie fraction (car certains bits sont utilisés pour la partie entière). Les grands nombres ont zéro bits pour la partie fraction.

Lorsque float est une norme IEEE-754 binaire de valeur à virgule flottante de 32 bits, ce qui est courant dans les implémentations modernes, la plus grande float ci-dessous est une 0,999999940395355224609375. Lorsque les routines qui convertissent les nombres décimaux en float sont de bonne qualité et que le mode d'arrondi est le plus proche (défaut commun), le point où les chiffres passent de 0,999999940395355224609375 à arrondi à 1 se situe à mi-chemin entre ces deux valeurs (et la valeur exacte). point milieu arrondira à 1).

La conversion correcte des nombres décimaux en points flottants binaires est compliquée. C'est un problème résolu et il existe des articles académiques à ce sujet, mais vous devriez généralement vous fier au code de bibliothèque existant, s'il fait le travail correctement. Si vous le faites correctement, vous devrez investir beaucoup de temps.

1

La question que je pose est comment puis-je calculer la fraction maximale qu'un flotteur peut exprimer. Comment puis-je, faute d'un meilleur terme, savoir quand un flotteur est sur le point de déborder?

Vous recherchez:

#include <math.h> 
… nextafterf(1.0f, 0.0f) … 

Mais vous devez vous familiariser avec la notation hexadécimale de C99 pour les flotteurs, et alors vous pouvez écrire directement la constante: 0x1.fffffep-1.

+0

ou '0x.ffffffp0' –