boost :: lexical_cast jest przesyłany strumieniowo.
TimW
1
Myślę, że generalnie nie można powiedzieć, że wiążą się one z obniżeniem wydajności. Pomyśl o tym, co się dzieje, gdy tuż przed tym masz cin >> num ;. Użytkownik musiałby pisać bardzo szybko (jak rly jon skeet), aby kiedykolwiek zauważyć, że milisekundy lexical_cast jest wolniejsze :) To powiedziawszy, uważam, że są zadania, w których lexical_cast po prostu wysysa zbyt dużo wydajności :)
Johannes Schaub - litb
3
Co robi dla tego rozwiązania :: przed atof ()? Co to musi tam być?
sivabudh
4
@ShaChris Ponieważ chcę się upewnić, że używam funkcji atof z globalnej przestrzeni nazw.
TimW
1
zależy od lokalizacji
nmr
104
Biblioteka standardowa (C ++ 11) oferuje pożądaną funkcjonalność dzięki std::stod:
std::string s ="0.6"
std::wstring ws ="0.7"double d = std::stod(s);double dw = std::stod(ws);
Ogólnie dla większości innych podstawowych typów, zobacz <string>. Jest też kilka nowych funkcji dla łańcuchów C. Widzieć<stdlib.h>
Podoba mi się to rozwiązanie, ale wygląda na to, że pochodzi tylko z C ++ 11. Więc niedostępne w moim SDK.
pamplemousse_mk2
To świetnie wiedzieć, że komisja C ++ standardy dodanych w tym. ostringstreamsam w sobie był po prostu zbyt długi, aby pisać, nie mówiąc już o użyciu ...
bobobobo
4
W przypadku pływaków (jak zadałem w pytaniu, które znalazłem w Google, wpisując „c ++ string to float”), należy użyć std :: stof.
Étienne
1
Tylko uwaga, że może to spowodować wyjątki: std :: invalid_argument (jeśli konwersja nie powiodła się) std :: out_of_range (jeśli poza zakresem)
Jason Doucette
3
Kupujący, strzeż się, zależy od aktualnej lokalizacji.
Dzięki, to działa ... Ale to dla mnie pytanie: dlaczego mój kod nie działa.
Max Frai
2
@Johannes Schaub: Opierając się na ADL, równie dobrze mógłby mieć, użycie definicji plus to, czego faktycznie używa, prawdopodobnie wprowadzi w zakres ogromną liczbę standardowych elementów. Ponadto lexical_cast jest niesamowicie powolny, więc nie otrzymuję ode mnie +1.
Fajną cechą boost :: lexical_cast jest obsługa błędów. Jeśli konwersja się nie powiedzie, zostanie wyrzucony wyjątek:try { ... boost::lexical_cast ... } catch (std::exception const& err) { //handle excpetion }
Semjon Mössinger
Aby być bardziej precyzyjnym, użyj catch ( boost::bad_lexical_cast const& err )do wychwycenia wyjątku.
Semjon Mössinger
14
Możesz użyć 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, więc myślisz, że boost :: lexical_cast ma okropny interfejs, prawda? Spójrz na odpowiedź StefanaB! Boost robi to samo.
kirsche40
@ kirsche40 Wygląda na dobrą alternatywę dla osób, które nie mają jeszcze zależności z Boostem (łączenie z Boostem tylko w celu konwersji std :: string na liczby to trochę przesada!)
Jean-Philippe Jodoin
@ JEan-Phillippe Jodiun Odpowiedziałem na usunięty komentarz, w którym ktoś polecił Boost. Zdaję sobie sprawę, że Boost to przeważnie przesada. Nawiasem mówiąc, od jakiegoś czasu użycie Boost jest ograniczone do "nowszych" kompilatorów. Starsze projekty nie mogą korzystać z funkcji Boost. Na przykład ASIO zależy w dużej mierze od funkcji C ++ 11, takich jak std :: addressof, co czyni go całkowicie bezwartościowym dla kompilatorów C ++ 98 / C ++ 03. IMHO, kiedy projekt zaczynał się, celem Boost było zapewnienie nowych "standardowych" funkcji dla starszych wersji kompilatorów ... :-(
kirsche40
10
Tak, z obsadą leksykalną. Użyj stringstream i operatora << lub użyj Boost, oni już to zaimplementowali.
Twoja własna wersja mogłaby wyglądać następująco:
template<typename to,typename from>to lexical_cast(from const&x){
std::stringstream os;
to ret;
os << x;
os >> ret;return ret;}
Uwaga: boost :: lexical_cast zgłasza wyjątek, więc powinieneś być przygotowany na poradzenie sobie z tym, gdy przekazujesz nieprawidłową wartość, spróbuj przekazać string ("xxx")
Nieprawidłowa odpowiedź, skąd wiesz, że wartość przechowywana w num jest w rzeczywistości poprawną liczbą zmiennoprzecinkową? nie sprawdzasz zwracanego typu sscanf, wygląda na to, że jest to styl kodowania MS.
1
Ta odpowiedź jest kopią zapasową w twoich komentarzach. Mam głębokie podejrzenie, że po prostu nie wyświetlasz poprawnie wyniku.
Kiedyś spotkało mnie dokładnie to samo. Spędziłem cały dzień próbując dowiedzieć się, dlaczego otrzymałem złą wartość w 64-bitowym int, tylko po to, by odkryć, że printf ignoruje drugi bajt. Nie możesz po prostu przekazać 64-bitowej wartości do printf, tak jak jest to int.
Nie używam printf, aby zobaczyć wyniki ... I używam tej wartości do ustawienia krycia okna, a moje okno jest w pełni przezroczyste, więc wartość wynosi 0.
Max Frai
1
Sposób C ++ 11 polega na użyciu std :: stod i std :: to_string. Oba działają w programie Visual Studio 11.
Co do tego, dlaczego atof()nie działa w pierwotnym pytaniu: fakt, że jest obsadzony podwójnie, budzi we mnie podejrzenia. Kod nie powinien się kompilować bez #include <stdlib.h>, ale jeśli rzutowanie zostało dodane w celu rozwiązania ostrzeżenia o kompilacji, atof()nie jest poprawnie zadeklarowane. Jeśli kompilator zakłada, że atof()zwraca wartość typu int, rzutowanie go rozwiąże ostrzeżenie o konwersji, ale nie spowoduje, że wartość zwracana zostanie rozpoznana jako podwójna.
#include<stdlib.h>#include<string>...
std::string num ="0.6";double temp = atof(num.c_str());
I tak nie chcesz Boost lexical_cast dla ciągu <-> zmiennoprzecinkowego. Ten podzbiór przypadków użycia jest jedynym zestawem, dla którego wzmocnienie konsekwentnie jest gorsze niż starsze funkcje - i zasadniczo skoncentrowały tam wszystkie swoje awarie, ponieważ ich własne wyniki wydajności pokazują 20-25X MNIEJSZĄ wydajność niż użycie sscanf i printf do takich konwersji.
Google to sam. boost :: lexical_cast może obsłużyć około 50 konwersji, a jeśli wykluczysz te, które zawierają zmiennoprzecinkowe #, będzie to równie dobre lub lepsze, jak oczywiste alternatywy (z dodatkową zaletą posiadania jednego interfejsu API dla wszystkich tych operacji). Ale przynieś pływaki i pod względem wydajności to jak Titanic uderzający w górę lodową.
Wszystkie stare, dedykowane funkcje str-> double mogą wykonać 10000 parsów w czasie około 30 ms (lub lepszym). lexical_cast wykonuje to samo przez około 650 ms.
Niezależny od ustawień regionalnych ciąg znaków do podwójnego (separator dziesiętny zawsze „.”)
Wykrywanie błędu w przypadku niepowodzenia konwersji ciągu
Moje rozwiązanie (używa funkcji 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 ... zajęło mi dość długo dotarcie do tego rozwiązania. I nadal mam wrażenie, że nie wiem wystarczająco dużo o lokalizacji ciągów znaków i tak dalej ...
Odpowiedzi:
Czy to dla mnie, poprawną składnią C ++ jest konwertowanie ciągu znaków na podwójny.
Możesz to zrobić za pomocą stringstream lub boost :: lexical_cast, ale wiąże się to z obniżeniem wydajności.
Ahaha, masz projekt Qt ...
Dodatkowa uwaga:
jeśli dane wejściowe to a
const char*
,QByteArray::toDouble
będzie szybsze.źródło
Biblioteka standardowa (C ++ 11) oferuje pożądaną funkcjonalność dzięki
std::stod
:Ogólnie dla większości innych podstawowych typów, zobacz
<string>
. Jest też kilka nowych funkcji dla łańcuchów C. Widzieć<stdlib.h>
źródło
ostringstream
sam w sobie był po prostu zbyt długi, aby pisać, nie mówiąc już o użyciu ...Obsada leksykalna jest bardzo fajna.
źródło
try { ... boost::lexical_cast ... } catch (std::exception const& err) { //handle excpetion }
catch ( boost::bad_lexical_cast const& err )
do wychwycenia wyjątku.Możesz użyć std :: stringstream:
Stosowanie:
źródło
Tak, z obsadą leksykalną. Użyj stringstream i operatora << lub użyj Boost, oni już to zaimplementowali.
Twoja własna wersja mogłaby wyglądać następująco:
źródło
Możesz użyć wzmocnienia leksykalnego rzutowania:
Uwaga: boost :: lexical_cast zgłasza wyjątek, więc powinieneś być przygotowany na poradzenie sobie z tym, gdy przekazujesz nieprawidłową wartość, spróbuj przekazać string ("xxx")
źródło
Jeśli nie chcesz, aby przeciągnąć na cały impuls, iść z
strtod(3)
od<cstdlib>
- to już wraca podwójnie.Wyjścia:
Dlaczego atof () nie działa ... na jakiej platformie / kompilatorze jesteś?
źródło
Miałem ten sam problem w Linuksie
to działa.
źródło
źródło
Ta odpowiedź jest kopią zapasową w twoich komentarzach. Mam głębokie podejrzenie, że po prostu nie wyświetlasz poprawnie wyniku.
Kiedyś spotkało mnie dokładnie to samo. Spędziłem cały dzień próbując dowiedzieć się, dlaczego otrzymałem złą wartość w 64-bitowym int, tylko po to, by odkryć, że printf ignoruje drugi bajt. Nie możesz po prostu przekazać 64-bitowej wartości do printf, tak jak jest to int.
źródło
Sposób C ++ 11 polega na użyciu std :: stod i std :: to_string. Oba działają w programie Visual Studio 11.
źródło
Co do tego, dlaczego
atof()
nie działa w pierwotnym pytaniu: fakt, że jest obsadzony podwójnie, budzi we mnie podejrzenia. Kod nie powinien się kompilować bez#include <stdlib.h>
, ale jeśli rzutowanie zostało dodane w celu rozwiązania ostrzeżenia o kompilacji,atof()
nie jest poprawnie zadeklarowane. Jeśli kompilator zakłada, żeatof()
zwraca wartość typu int, rzutowanie go rozwiąże ostrzeżenie o konwersji, ale nie spowoduje, że wartość zwracana zostanie rozpoznana jako podwójna.powinien działać bez ostrzeżeń.
źródło
Zamiast przeciągać Boost do równania, możesz zachować strunę (tymczasowo) jako a
char[]
i użyćsprintf()
.Ale oczywiście, jeśli i tak używasz Boost, to naprawdę nie jest to zbyt duży problem.
źródło
I tak nie chcesz Boost lexical_cast dla ciągu <-> zmiennoprzecinkowego. Ten podzbiór przypadków użycia jest jedynym zestawem, dla którego wzmocnienie konsekwentnie jest gorsze niż starsze funkcje - i zasadniczo skoncentrowały tam wszystkie swoje awarie, ponieważ ich własne wyniki wydajności pokazują 20-25X MNIEJSZĄ wydajność niż użycie sscanf i printf do takich konwersji.
Google to sam. boost :: lexical_cast może obsłużyć około 50 konwersji, a jeśli wykluczysz te, które zawierają zmiennoprzecinkowe #, będzie to równie dobre lub lepsze, jak oczywiste alternatywy (z dodatkową zaletą posiadania jednego interfejsu API dla wszystkich tych operacji). Ale przynieś pływaki i pod względem wydajności to jak Titanic uderzający w górę lodową.
Wszystkie stare, dedykowane funkcje str-> double mogą wykonać 10000 parsów w czasie około 30 ms (lub lepszym). lexical_cast wykonuje to samo przez około 650 ms.
źródło
Mój problem:
Moje rozwiązanie (używa funkcji Windows _wcstod_l):
HTH ... zajęło mi dość długo dotarcie do tego rozwiązania. I nadal mam wrażenie, że nie wiem wystarczająco dużo o lokalizacji ciągów znaków i tak dalej ...
źródło