2009-12-29 33 views
7

que tiene una cadena que tiene este aspecto:de formato de cadena en notación científica

"0.4794255386042030002732879352156" 

que es aproximadamente el pecado (0,5). Me gustaría formatear la cadena para que se vea mucho mejor

"4.794255386042e-1" 

¿Cómo puedo lograr esto? Recuerda que estoy lidiando con cadenas y no números (float, double). También necesito redondear para mantener el número lo más preciso posible, no puedo truncar. Si necesito convertir a un tipo de datos diferente, preferiría un doble largo porque un doble regular no tiene la precisión suficiente. Me gustaría al menos 12 dígitos decimales antes de redondear. Tal vez haya una conversión simple de sprintf() que podría hacer.

Respuesta

8

Algo como esto:

#include<iostream> 
using namespace std; 

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

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

     return EXIT_SUCCESS; 
} 

Salida:

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

No hay una función estándar en C o C++ para hacer esto. El enfoque normal es convertir a un número (y luego usar funciones estándar para formatear el número) o escribir su propia función de salida personalizada.

2

En altamente portátil C el ejemplo de trabajo por debajo de las salidas:

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

No, que da salida a 0,4794255386042030002732879352156, que no es lo que pidió. – dcp

+0

No, produce 4.794255e-01 (la precisión predeterminada es 6). 'cout.precision (12)' lo configuraría en doce. –

1

Convertir a largo doble usando sscanf(), a continuación, utilizar sprintf() a imprimir de nuevo como una cadena, usando el formateador científica:

long double x; 
char num[64]; 

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

No estoy seguro si incluso long double en realidad le da 12 dígitos significativos, sin embargo. En mi sistema, esto genera "4.79425538604e-01".

+0

¿quisiste decir si (sscanf (cadena, "% Lf", & x) == 1) porque% Ld da un entero largo? –

+0

@John: ¡Sí, gracias! – unwind

0

Dependiendo de cuántos decimales desea (12 en este caso) se podría hacer algo como esto:

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; 
} 

Resultado: ---------- --- salida de captura -------

"c: \ windows \ system32 \ cmd.exe" /cc:\temp\temp.exe 4.794255386042e-1 Terminado con código de salida 0.

2

Al observar las cadenas en su pregunta, parecería que está utilizando logaritmos de base 10. En ese caso, ¿no sería relativamente fácil contar los ceros iniciales o finales y ponerlos en un exponente, escaneando las cadenas directamente?

Tal vez me falta algo ..

+0

De acuerdo. En este caso, simplemente podría encontrar la posición del punto, moverlo y anexar el exponente como un recuento de qué tan lejos y en qué dirección se movió el punto. – Clifford

1

Un IEEE 754 de 64 bits flotante (es decir, de doble precisión), que es bueno para 15 cifras decimales significativos, por lo que no debería tener problemas para doblar la conversión. Es más probable que se encuentre con el problema de hacer que el especificador de formato muestre todos los dígitos disponibles. Aunque de los ejemplos publicados, este no parece ser el caso.

+0

tiene razón, un doble es lo suficientemente bueno una vez que agregué una cadena de formato adecuada, incluso obtuve 17 dígitos decimales de un doble, estoy seguro de que podría obtener más pero eso es suficiente. –

+0

¡No con un doble no podrías! De hecho, ni siquiera 17 es posible independientemente de lo que tengas que tengas. La mantisa es de 52 bits, 2^52 es un número decimal de 16 dígitos, por lo que el límite es de 15 dígitos (matemáticamente 15.65 dígitos) porque 52 bits es suficiente para representar todos los números posibles de 15 dígitos. Tenga en cuenta que estoy hablando de * cifras significativas * no lugares decimales. – Clifford

6

¿Está buscando algo como this?

Este es un ejemplo:

// 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; 
} 

Salida:

0,479425538604203005377257795772

4.79426e-01

Cuestiones relacionadas