2009-12-29 9 views
7

J'ai une chaîne qui ressemble à ceci:Chaîne de format en notation scientifique

"0.4794255386042030002732879352156" 

qui est à peu près le péché (0,5). Je voudrais formater la chaîne à regarder beaucoup plus agréable

"4.794255386042e-1" 

Comment puis-je y parvenir? Rappelez-vous que j'ai affaire à des cordes et non à des nombres (float, double). Aussi je dois arrondir pour garder le nombre aussi précis que possible, je ne peux pas juste tronquer. Si je dois convertir en un type de données différent, je préférerais un double long car un double régulier n'a pas assez de précision. Je voudrais au moins 12 chiffres décimaux avant d'arrondir. Peut-être qu'il y a une simple conversion de sprintf() que je pourrais faire.

Répondre

8

Quelque chose comme ceci:

#include<iostream> 
using namespace std; 

int main() 
{ 
     char *s = "0.4794255386042030002732879352156"; 
     double d; 

     sscanf(s,"%lf",&d); 
     printf("%.12e\n",d); 

     return EXIT_SUCCESS; 
} 

Sortie:

# g++ a.cpp && ./a.out 
4.794255386042e-01 
0

Il n'existe aucune fonction standard en C ou C++ pour ce faire. L'approche normale consiste soit à convertir en un nombre (puis à utiliser des fonctions standard pour formater le nombre) ou à écrire votre propre fonction de sortie personnalisée.

2

Dans C très portable l'exemple de travail ci-dessous sorties:

result is 4.794255386042E-01 


#include <stdio.h> 

int main() 
{ 
    char *str = "0.4794255386042030002732879352156"; 

    double f; 
    char newstr [50]; 
    // convert string in `str` to float 
    sscanf (str, "%le", &f); 

    sprintf (newstr, "%.12E", f); 
    printf ("result is %s\n", newstr); 
    return 0; 
} 
0
#include <iostream> 
using namespace std; 
... 
double dd = strtod(str); 
cout << scientific << dd << endl; 
+0

Non, qui sort 0,4794255386042030002732879352156, ce qui est pas ce qu'il a demandé. – dcp

+0

Non, il affiche 4.794255e-01 (la précision par défaut est 6). 'Cout.precision (12)' le fixerait à douze. –

1

Convertir en long double en utilisant sscanf(), puis utilisez sprintf() pour l'imprimer arrière comme une chaîne, en utilisant le formatter scientifique:

long double x; 
char num[64]; 

if(sscanf(string, "%Lf", &x) == 1) 
    sprintf(num, "%.12Le", x); 

Je ne sais pas si même long double vous donne en fait 12 chiffres significatifs, cependant. Sur mon système, cela génère "4.79425538604e-01".

+0

vouliez-vous dire si (sscanf (string, "% Lf", & x) == 1) parce que% Ld donne un entier long? –

+0

@John: Oui, merci! – unwind

0

Selon le nombre de décimales (12 dans ce cas), vous pouvez faire quelque chose comme ceci:

int main() { 
    char buff[500]; 
    string x = "0.4794255386042030002732879352156"; 
    double f = atof(x.c_str()); 
    sprintf(buff,"%.12fe-1",f*10); 
    cout<<buff<<endl; 
    return 0; 
} 

Résultat: ---------- --- Sortie de capture -------

"c: \ windows \ system32 \ cmd.exe" /cc:\temp\temp.exe 4.794255386042e-1 Terminated avec le code de sortie 0.

2

En regardant les chaînes dans votre question, il semblerait que vous utilisez les logarithmes de base 10. Dans ce cas, ne serait-il pas relativement facile de simplement compter les zéros en tête ou en queue et de les mettre dans un exposant, en scannant directement les chaînes?

Peut-être que je manque quelque chose ..

+0

D'accord. Dans ce cas, il pourrait simplement trouver la position du point, le déplacer et ajouter l'exposant comme un compte de la distance et de la direction dans laquelle le point a été déplacé. – Clifford

1

Un flotteur bits IEEE 754 64 (à savoir double précision), est bon pour 15 chiffres significatifs décimaux, de sorte que vous ne devriez avoir aucun problème pour doubler la conversion. Vous êtes plus susceptible de rencontrer le problème d'obtenir le spécificateur de format pour afficher tous les chiffres disponibles. Bien que d'après les exemples affichés, cela ne semble pas être le cas.

+0

vous avez raison un double est assez bon une fois que j'ai ajouté dans une chaîne de format correct j'ai même obtenu 17 chiffres décimaux sur un double, je suis sûr que je pourrais obtenir plus mais c'est beaucoup. –

+0

Pas avec un double vous ne pouviez pas! En fait, même 17 n'est pas possible, peu importe ce que vous avez. La mantisse est 52 bits, 2^52 est un nombre décimal de 16 chiffres, donc la limite est de 15 chiffres (mathématiquement 15,65 chiffres) parce que 52 bits est suffisant pour représenter tous les nombres de 15 chiffres possibles. Notez que je parle de * chiffres significatifs * pas de décimales. – Clifford

6

Vous cherchez quelque chose comme this?

Voici un exemple:

// modify basefield 
#include <iostream> 
#include <sstream> 

using namespace std; 

int main() { 
    std::string numbers("0.4794255386042030002732879352156"); 
    std::stringstream stream; 
    stream << numbers; 
    double number_fmt; 
    stream >> number_fmt; 
    cout.precision(30); 

    cout << number_fmt << endl; 

    cout.precision(5); 
    cout << scientific << number_fmt << endl; 
    return 0; 
} 

Sortie:

0,479425538604203005377257795772

4.79426e-01

Questions connexes