En general, no se puede decir que vienen con una penalización de rendimiento, creo. Piense en lo que sucede cuando justo antes tiene un cin >> num ;. El usuario tendría que escribir muy rápido (rly jon skeet like) para notar que los milisegundos lexical_cast son más lentos :) Dicho esto, creo que hay tareas en las que lexical_cast simplemente apesta demasiado rendimiento :)
Johannes Schaub - litb
3
Para esta solución, ¿qué hace el :: delante de atof ()? ¿Qué necesita para estar ahí?
sivabudh
4
@ShaChris Porque quiero asegurarme de usar la función atof del espacio de nombres global.
TimW
1
depende de la ubicación actual
RMN
104
La biblioteca estándar (C ++ 11) ofrece la funcionalidad deseada con std::stod:
std::string s ="0.6"
std::wstring ws ="0.7"double d = std::stod(s);double dw = std::stod(ws);
Generalmente para la mayoría de los otros tipos básicos, consulte <string>. También hay algunas características nuevas para las cuerdas C. Ver<stdlib.h>
Me gusta esta solución, pero parece que es solo de C ++ 11. Por lo tanto, no está disponible en mi SDK.
pamplemousse_mk2
Es genial saber que el comité de estándares de C ++ agregó esto. ostringstreamen sí era simplemente demasiado tiempo para escribir a máquina, dejar que su uso solo ..
bobobobo
4
Para los flotadores (como se hace en la pregunta que encontré con google escribiendo "c ++ string to float"), se debe usar std :: stof.
Étienne
1
Solo una nota de que esto puede generar excepciones: std :: invalid_argument (si la conversión falló) std :: out_of_range (si está fuera del rango)
Jason Doucette
3
Atención al comprador, depende de la ubicación actual.
Gracias, funciona ... Pero es una pregunta para mí: por qué mi código no funciona.
Max Frai
2
@Johannes Schaub: Basado en ADL, bien podría haberlo hecho, las definiciones de uso más lo que realmente está usando probablemente traerán al alcance una gran cantidad de elementos estándar. Además, lexical_cast es increíblemente lento, así que no tengo +1 de mi parte.
Una buena característica de boost :: lexical_cast es el manejo de errores. Si falla una conversión, se lanza una excepción:try { ... boost::lexical_cast ... } catch (std::exception const& err) { //handle excpetion }
Semjon Mössinger
Para ser más precisos, use catch ( boost::bad_lexical_cast const& err )para capturar la excepción.
Semjon Mössinger
14
Puede usar std :: stringstream:
#include<sstream>#include<string>template<typename T>
T StringToNumber(const std::string& numberAsString){
T valor;
std::stringstream stream(numberAsString);
stream >> valor;if(stream.fail()){
std::runtime_error e(numberAsString);throw e;}return valor;}
Uhm, entonces crees que boost :: lexical_cast tiene una interfaz terrible, ¿no? ¡Mira la respuesta de stefanB! Boost hace lo mismo.
kirsche40
@ kirsche40 Parece una buena alternativa para las personas que aún no tienen dependencias con Boost (¡vincular con Boost solo para convertir un std :: string en números es un poco exagerado!)
Jean-Philippe Jodoin
@ JEan-Phillippe Jodiun Respondí a un comentario ahora eliminado, donde alguien recomendó Boost. Soy consciente de que Boost es la mayoría de las veces exagerado. Por cierto, desde hace algún tiempo el uso de Boost está restringido a compiladores "más nuevos". Los proyectos más antiguos no pueden usar Boost. Por ejemplo, ASIO depende en gran medida de características de C ++ 11 como std :: addressof, lo que lo hace completamente inútil para los compiladores de C ++ 98 / C ++ 03. En mi humilde opinión, cuando comenzó el proyecto, la intención de Boost era proporcionar nuevas características "estandarizadas" para versiones de compilador más antiguas ... :-(
kirsche40
10
Sí, con tinte léxico. Use un stringstream y el operador <<, o use Boost, ya lo han implementado.
Su propia versión podría verse así:
template<typename to,typename from>to lexical_cast(from const&x){
std::stringstream os;
to ret;
os << x;
os >> ret;return ret;}
Nota: boost :: lexical_cast lanza una excepción, por lo que debe estar preparado para lidiar con eso cuando pase un valor no válido, intente pasar la cadena ("xxx")
Respuesta inválida, ¿cómo sabe que el valor almacenado en num es en realidad un número de punto flotante válido? no verifica el tipo de retorno de sscanf, parece un estilo de codificación MS.
1
Esta respuesta está respaldando litb en sus comentarios. Tengo profundas sospechas de que simplemente no está mostrando el resultado correctamente.
Una vez me pasó exactamente lo mismo. Pasé un día entero tratando de averiguar por qué obtenía un valor incorrecto en un int de 64 bits, solo para descubrir que printf ignoraba el segundo byte. No puede simplemente pasar un valor de 64 bits a printf como si fuera un int.
No estoy usando printf para ver los resultados ... Y uso ese valor para establecer la opacidad de la ventana, y mi ventana es completamente transparente, por lo que el valor es 0.
Max Frai
1
La forma de C ++ 11 es usar std :: stod y std :: to_string. Ambos funcionan en Visual Studio 11.
En cuanto a por qué atof()no funciona en la pregunta original: el hecho de que esté emitido al doble me hace sospechar. El código no debería compilarse sin #include <stdlib.h>, pero si la conversión se agregó para resolver una advertencia de compilación, entonces atof()no se declara correctamente. Si el compilador asume atof()devuelve un int, fundición que va a resolver el aviso de conversión, pero será no causa el valor devuelto a ser reconocido como un doble.
#include<stdlib.h>#include<string>...
std::string num ="0.6";double temp = atof(num.c_str());
De todos modos, no desea Boost lexical_cast para string <-> punto flotante. Ese subconjunto de casos de uso es el único conjunto en el que el impulso consistentemente es peor que las funciones anteriores, y básicamente concentraron todas sus fallas allí, porque sus propios resultados de rendimiento muestran un rendimiento 20-25X MÁS LENTO que usar sscanf e printf para tales conversiones.
Búscalo tú mismo. boost :: lexical_cast puede manejar algo así como 50 conversiones y si excluye las que involucran números de punto flotante, es tan buena o mejor como las alternativas obvias (con la ventaja adicional de tener una única API para todas esas operaciones). Pero trae flotadores y es como si el Titanic golpeara un iceberg en términos de rendimiento.
Las antiguas funciones str-> double dedicadas pueden realizar 10000 análisis en algo así como 30 ms (o mejor). lexical_cast tarda unos 650 ms en hacer el mismo trabajo.
Cadena independiente de configuración regional para duplicar (separador decimal siempre '.')
Detección de errores si falla la conversión de cadenas
Mi solución (usa la función de Windows _wcstod_l):
// string to convert. Note: decimal seperator is ',' here
std::wstring str = L"1,101";// Use this for error detectionwchar_t* stopString;// Create a locale for "C". Thus a '.' is expected as decimal separatordouble dbl = _wcstod_l(str.c_str(),&stopString, _create_locale(LC_ALL,"C"));if(wcslen(stopString)!=0){// ... error handling ... we'll run into this because of the separator}
HTH ... me tomó bastante tiempo llegar a esta solución. Y todavía tengo la sensación de que no sé lo suficiente sobre localización de cadenas y esas cosas ...
Respuestas:
Lo hace por mí, es una sintaxis válida de C ++ para convertir una cadena en un doble.
Puede hacerlo con stringstream o boost :: lexical_cast, pero esos vienen con una penalización de rendimiento.
Ahaha tienes un proyecto Qt ...
Nota adicional:
si los datos de entrada son a
const char*
,QByteArray::toDouble
será más rápido.fuente
La biblioteca estándar (C ++ 11) ofrece la funcionalidad deseada con
std::stod
:Generalmente para la mayoría de los otros tipos básicos, consulte
<string>
. También hay algunas características nuevas para las cuerdas C. Ver<stdlib.h>
fuente
ostringstream
en sí era simplemente demasiado tiempo para escribir a máquina, dejar que su uso solo ..El elenco léxico es muy agradable.
fuente
try { ... boost::lexical_cast ... } catch (std::exception const& err) { //handle excpetion }
catch ( boost::bad_lexical_cast const& err )
para capturar la excepción.Puede usar std :: stringstream:
Uso:
fuente
Sí, con tinte léxico. Use un stringstream y el operador <<, o use Boost, ya lo han implementado.
Su propia versión podría verse así:
fuente
Puede utilizar el elenco léxico de impulso:
Nota: boost :: lexical_cast lanza una excepción, por lo que debe estar preparado para lidiar con eso cuando pase un valor no válido, intente pasar la cadena ("xxx")
fuente
Si no desea arrastrar todo el impulso, vaya con
strtod(3)
desde<cstdlib>
: ya devuelve un doble.Salidas:
¿Por qué atof () no funciona ... en qué plataforma / compilador estás?
fuente
Tuve el mismo problema en Linux
funciona.
fuente
fuente
Esta respuesta está respaldando litb en sus comentarios. Tengo profundas sospechas de que simplemente no está mostrando el resultado correctamente.
Una vez me pasó exactamente lo mismo. Pasé un día entero tratando de averiguar por qué obtenía un valor incorrecto en un int de 64 bits, solo para descubrir que printf ignoraba el segundo byte. No puede simplemente pasar un valor de 64 bits a printf como si fuera un int.
fuente
La forma de C ++ 11 es usar std :: stod y std :: to_string. Ambos funcionan en Visual Studio 11.
fuente
En cuanto a por qué
atof()
no funciona en la pregunta original: el hecho de que esté emitido al doble me hace sospechar. El código no debería compilarse sin#include <stdlib.h>
, pero si la conversión se agregó para resolver una advertencia de compilación, entoncesatof()
no se declara correctamente. Si el compilador asumeatof()
devuelve un int, fundición que va a resolver el aviso de conversión, pero será no causa el valor devuelto a ser reconocido como un doble.debería funcionar sin advertencias.
fuente
En lugar de arrastrar Boost a la ecuación, puede mantener su cadena (temporalmente) como
char[]
y usarsprintf()
.Pero, por supuesto, si está usando Boost de todos modos, realmente no es un gran problema.
fuente
De todos modos, no desea Boost lexical_cast para string <-> punto flotante. Ese subconjunto de casos de uso es el único conjunto en el que el impulso consistentemente es peor que las funciones anteriores, y básicamente concentraron todas sus fallas allí, porque sus propios resultados de rendimiento muestran un rendimiento 20-25X MÁS LENTO que usar sscanf e printf para tales conversiones.
Búscalo tú mismo. boost :: lexical_cast puede manejar algo así como 50 conversiones y si excluye las que involucran números de punto flotante, es tan buena o mejor como las alternativas obvias (con la ventaja adicional de tener una única API para todas esas operaciones). Pero trae flotadores y es como si el Titanic golpeara un iceberg en términos de rendimiento.
Las antiguas funciones str-> double dedicadas pueden realizar 10000 análisis en algo así como 30 ms (o mejor). lexical_cast tarda unos 650 ms en hacer el mismo trabajo.
fuente
Mi problema:
Mi solución (usa la función de Windows _wcstod_l):
HTH ... me tomó bastante tiempo llegar a esta solución. Y todavía tengo la sensación de que no sé lo suficiente sobre localización de cadenas y esas cosas ...
fuente