Convertir double / float en chaîne

J’ai besoin de convertir un nombre à virgule flottante en une chaîne équivalente en décimal (ou autre base). La conversion doit d’abord être effectuée au format xE+0x est le nombre à virgule flottante.

L’idée que j’ai est d’abord de tronquer le nombre à virgule flottante en un entier temporaire, puis de convertir cet entier en chaîne, puis d’envisager la partie fractionnaire et de la multiplier par 10 alors que la partie fractionnaire ne devient pas 0 . Une fois que la partie fractionnaire est transférée dans la partie gauche du point décimal, appliquez à nouveau l’entier à la fonction chaîne et convertissez la partie fraction en chaîne. Y a-t-il un meilleur moyen, qui sera plus rapide que cela? Cette méthode provoquera-t-elle des effets secondaires?

Pour convertir le nombre à virgule flottante en représentation exponentielle, dois-je faire comme ci-dessus, puis régler la puissance? Vous pouvez également masquer directement la représentation à virgule flottante IEEE 754 et convertir chaque partie en chaîne.

Remarque: Aucune autre fonction ne peut être utilisée, car je n’ai access à aucune fonction de bibliothèque. Ce code va dans un kernel de jouet.

La seule solution exacte consiste à effectuer une arithmétique décimale de précision arbitraire pour la conversion de base, car la valeur exacte peut être très longue – pour un long double de 80 bits, jusqu’à environ 10000 décimales. Heureusement, il ne s’agit “que” d’un maximum de 700 places environ pour IEEE double .

Plutôt que de travailler avec des chiffres décimaux individuels, il est utile de travailler au lieu de 1 milliard de base (la plus grande puissance de 10 logée dans un entier de 32 bits), puis de convertir ces “1 milliard de chiffres de base” en 9 chiffres décimaux chacun. à la fin de votre calcul.

J’ai une implémentation très dense (assez difficile à lire) mais efficace ici, sous licence LGPL MIT:

http://git.musl-libc.org/cgit/musl/blob/src/stdio/vfprintf.c?h=v1.1.6

Si vous supprimez tout le support de flottement d’hex, le support infini / nan, le support de variation %g / %f / %e , l’arrondi (qui ne sera jamais nécessaire si vous ne voulez que des réponses exactes), et d’autres éléments dont vous pourriez ne pas avoir besoin, les le code restant est plutôt simple.

Utilisez snprintf() partir de stdlib.h . Travaillé pour moi

 double num = 123412341234.123456789; char output[50]; snprintf(output, 50, "%f", num); printf("%s", output); 

Allez regarder l’implémentation printf() avec "%f" dans une bibliothèque C.

Je sais que c’est peut-être inutile, mais j’ai créé une fonction qui convertit float en chaîne:

CODE:

 #include  /** Number on countu **/ int n_tu(int number, int count) { int result = 1; while(count-- > 0) result *= number; return result; } /*** Convert float to ssortingng ***/ void float_to_ssortingng(float f, char r[]) { long long int length, length2, i, number, position, sign; float number2; sign = -1; // -1 == positive number if (f < 0) { sign = '-'; f *= -1; } number2 = f; number = f; length = 0; // Size of decimal part length2 = 0; // Size of tenth /* Calculate length2 tenth part */ while( (number2 - (float)number) != 0.0 && !((number2 - (float)number) < 0.0) ) { number2 = f * (n_tu(10.0, length2 + 1)); number = number2; length2++; } /* Calculate length decimal part */ for (length = (f > 1) ? 0 : 1; f > 1; length++) f /= 10; position = length; length = length + 1 + length2; number = number2; if (sign == '-') { length++; position++; } for (i = length; i >= 0 ; i--) { if (i == (length)) r[i] = '\0'; else if(i == (position)) r[i] = '.'; else if(sign == '-' && i == 0) r[i] = '-'; else { r[i] = (number % 10) + '0'; number /=10; } } } 

Utilisez ceci:

 void double_to_char(double f,char * buffer){ gcvt(f,10,buffer); } 

Vérifiez si la bibliothèque standard BSD C a fcvt (). Vous pouvez commencer par le source plutôt que d’écrire votre code à partir de zéro. La norme fcvt () standard UNIX 98 ne produit apparemment pas de notation scientifique, vous devez donc la mettre en œuvre vous-même, mais je ne pense pas que ce serait difficile.

sprintf peut faire ceci:

 #include  int main() { float w = 234.567; char x[__SIZEOF_FLOAT__]; sprintf(x, "%g", w); puts(x); }