Você geralmente não pode dizer que eles vêm com uma penalidade de desempenho, eu acho. Pense no que acontece quando um pouco antes disso você tem um cin >> num ;. O usuário teria que digitar muito rapidamente (como rly jon skeet) para notar os milissegundos que lexical_cast é mais lento :) Dito isso, acredito que há tarefas em que lexical_cast é muito ruim para o desempenho :)
Johannes Schaub - litb
3
Para esta solução, o que o :: na frente de atof () faz? O que é necessário para estar lá?
sivabudh
4
@ShaChris Porque quero ter certeza de usar a função atof do namespace global.
TimW
1
depende do local atual
nmr
104
A Biblioteca Padrão (C ++ 11) oferece a funcionalidade desejada com std::stod:
std::string s ="0.6"
std::wstring ws ="0.7"double d = std::stod(s);double dw = std::stod(ws);
Geralmente, para a maioria dos outros tipos básicos, consulte <string>. Existem alguns novos recursos para strings C também. Vejo<stdlib.h>
Obrigado, funciona .. Mas é uma questão para mim: por que meu código não está funcionando.
Max Frai de
2
@Johannes Schaub: Com base no ADL, ele pode muito bem ter feito isso, o uso de definições mais o que ele está realmente usando provavelmente trará para o escopo um grande número de elementos std. Além disso, lexical_cast é incrivelmente lento, então nenhum +1 de mim.
Um bom recurso de boost :: lexical_cast é o tratamento de erros. Se uma conversão falhar, uma exceção é lançada:try { ... boost::lexical_cast ... } catch (std::exception const& err) { //handle excpetion }
Semjon Mössinger
Para ser mais preciso, use catch ( boost::bad_lexical_cast const& err )para capturar a exceção.
Semjon Mössinger
14
Você pode 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, então você acha que boost :: lexical_cast tem uma interface terrível, não é? Veja a resposta de StefanB! Boost faz o mesmo.
kirsche40 de
@ kirsche40 Parece uma boa alternativa para pessoas que ainda não têm dependências com Boost (vincular com Boost apenas para converter uma string std :: em números é um pouco exagero!)
Jean-Philippe Jodoin
@ JEan-Phillippe Jodiun Eu respondi a um comentário agora excluído, onde alguém recomendou Boost. Estou ciente de que Boost é na maioria das vezes um exagero. A propósito, há algum tempo o uso do Boost é restrito a compiladores "mais novos". Projetos mais antigos não podem usar Boost. Por exemplo, o ASIO depende muito dos recursos do C ++ 11 como std :: addressof, o que o torna completamente inútil para os compiladores C ++ 98 / C ++ 03. IMHO, quando o projeto começou, a intenção da Boost era fornecer novos recursos "padronizados" para versões mais antigas do compilador ... :-(
kirsche40
10
Sim, com um molde léxico. Use um stringstream e o operador <<, ou use Boost, eles já o implementaram.
Sua própria versão pode ser semelhante a:
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 lança exceção, então você deve estar preparado para lidar com isso quando passar um valor inválido, tente passar string ("xxx")
Resposta inválida, como você sabe que o valor armazenado em num é realmente um número de ponto flutuante válido? você não verifica o tipo de retorno de sscanf, parece um estilo de codificação MS.
1
Esta resposta está apoiada em pouco nos seus comentários. Tenho profundas suspeitas de que você simplesmente não está exibindo o resultado corretamente.
A mesma coisa aconteceu comigo uma vez. Passei um dia inteiro tentando descobrir por que estava obtendo um valor ruim em um int de 64 bits, apenas para descobrir que printf estava ignorando o segundo byte. Você não pode simplesmente passar um valor de 64 bits para printf como se fosse um int.
Não estou usando printf para ver os resultados ... E eu uso esse valor para definir a opacidade da janela, e minha janela está totalmente transparente, então o valor é 0.
Max Frai
1
A maneira C ++ 11 é usar std :: stod e std :: to_string. Ambos funcionam no Visual Studio 11.
Quanto a por que atof()não está funcionando na pergunta original: o fato de que é lançado para dobrar me deixa desconfiado. O código não deve ser compilado sem #include <stdlib.h>, mas se o elenco foi adicionado para resolver um aviso de compilação, então atof()não foi declarado corretamente. Se o compilador assume atof()retorna um int, lançando ele vai resolver o aviso de conversão, mas vai não causa o valor de retorno para ser reconhecido como um duplo.
#include<stdlib.h>#include<string>...
std::string num ="0.6";double temp = atof(num.c_str());
Você não quer Boost lexical_cast para string <-> ponto flutuante de qualquer maneira. Esse subconjunto de casos de uso é o único em que o boost consistentemente é pior do que as funções mais antigas - e eles basicamente concentraram todas as suas falhas ali, porque seus próprios resultados de desempenho mostram um desempenho 20-25X MAIS LENTO do que usar sscanf e printf para tais conversões.
Pesquise no Google. boost :: lexical_cast pode lidar com algo como 50 conversões e se você excluir aquelas envolvendo ponto flutuante # é tão bom ou melhor quanto as alternativas óbvias (com a vantagem adicional de ter uma única API para todas essas operações). Mas traga carros alegóricos e é como o Titanic batendo em um iceberg em termos de desempenho.
As antigas funções str-> double dedicadas podem fazer 10.000 análises em cerca de 30 ms (ou melhor). lexical_cast leva algo como 650 ms para fazer o mesmo trabalho.
String independente de local para duplicar (separador decimal sempre '.')
Detecção de erro se a conversão de string falhar
Minha solução (usa a função do 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 ... demorei muito para chegar a essa solução. E ainda tenho a sensação de que não sei o suficiente sobre localização de cordas e outras coisas ...
Respostas:
Para mim, é uma sintaxe C ++ válida para converter uma string em um double.
Você pode fazer isso com stringstream ou boost :: lexical_cast, mas eles vêm com uma penalidade de desempenho.
Ahaha você tem um projeto Qt ...
Observação extra:
se os dados de entrada forem a
const char*
,QByteArray::toDouble
será mais rápido.fonte
A Biblioteca Padrão (C ++ 11) oferece a funcionalidade desejada com
std::stod
:Geralmente, para a maioria dos outros tipos básicos, consulte
<string>
. Existem alguns novos recursos para strings C também. Vejo<stdlib.h>
fonte
ostringstream
em si era simplesmente muito longo para digitar, quanto mais usar ..O elenco lexical é muito bom.
fonte
try { ... boost::lexical_cast ... } catch (std::exception const& err) { //handle excpetion }
catch ( boost::bad_lexical_cast const& err )
para capturar a exceção.Você pode usar std :: stringstream:
Uso:
fonte
Sim, com um molde léxico. Use um stringstream e o operador <<, ou use Boost, eles já o implementaram.
Sua própria versão pode ser semelhante a:
fonte
Você pode usar o reforço de elenco léxico:
Nota: boost :: lexical_cast lança exceção, então você deve estar preparado para lidar com isso quando passar um valor inválido, tente passar string ("xxx")
fonte
Se você não quiser arrastar todo o impulso, vá com
strtod(3)
de<cstdlib>
- ele já retorna um duplo.Saídas:
Por que atof () não funciona ... em qual plataforma / compilador você está?
fonte
Eu tive o mesmo problema no Linux
funciona.
fonte
fonte
Esta resposta está apoiada em pouco nos seus comentários. Tenho profundas suspeitas de que você simplesmente não está exibindo o resultado corretamente.
A mesma coisa aconteceu comigo uma vez. Passei um dia inteiro tentando descobrir por que estava obtendo um valor ruim em um int de 64 bits, apenas para descobrir que printf estava ignorando o segundo byte. Você não pode simplesmente passar um valor de 64 bits para printf como se fosse um int.
fonte
A maneira C ++ 11 é usar std :: stod e std :: to_string. Ambos funcionam no Visual Studio 11.
fonte
Quanto a por que
atof()
não está funcionando na pergunta original: o fato de que é lançado para dobrar me deixa desconfiado. O código não deve ser compilado sem#include <stdlib.h>
, mas se o elenco foi adicionado para resolver um aviso de compilação, entãoatof()
não foi declarado corretamente. Se o compilador assumeatof()
retorna um int, lançando ele vai resolver o aviso de conversão, mas vai não causa o valor de retorno para ser reconhecido como um duplo.deve funcionar sem avisos.
fonte
Em vez de arrastar Boost para a equação, você pode manter sua corda (temporariamente) como um
char[]
e usarsprintf()
.Mas é claro que se você estiver usando Boost de qualquer maneira, não é um grande problema.
fonte
Você não quer Boost lexical_cast para string <-> ponto flutuante de qualquer maneira. Esse subconjunto de casos de uso é o único em que o boost consistentemente é pior do que as funções mais antigas - e eles basicamente concentraram todas as suas falhas ali, porque seus próprios resultados de desempenho mostram um desempenho 20-25X MAIS LENTO do que usar sscanf e printf para tais conversões.
Pesquise no Google. boost :: lexical_cast pode lidar com algo como 50 conversões e se você excluir aquelas envolvendo ponto flutuante # é tão bom ou melhor quanto as alternativas óbvias (com a vantagem adicional de ter uma única API para todas essas operações). Mas traga carros alegóricos e é como o Titanic batendo em um iceberg em termos de desempenho.
As antigas funções str-> double dedicadas podem fazer 10.000 análises em cerca de 30 ms (ou melhor). lexical_cast leva algo como 650 ms para fazer o mesmo trabalho.
fonte
Meu problema:
Minha solução (usa a função do Windows _wcstod_l):
HTH ... demorei muito para chegar a essa solução. E ainda tenho a sensação de que não sei o suficiente sobre localização de cordas e outras coisas ...
fonte