Я думаю, вы не можете вообще сказать, что они идут со снижением производительности. Подумайте, что происходит, когда прямо перед этим у вас есть cin >> num ;. Пользователю придется набирать текст очень быстро (например, rly jon skeet), чтобы когда-либо заметить, что в миллисекундах lexical_cast медленнее :) Тем не менее, я считаю, что есть задачи, в которых lexical_cast просто отстойно сказывается на производительности :)
Йоханнес Шауб - litb
3
Что в этом решении делает :: перед atof ()? Что там должно быть?
sivabudh
4
@ShaChris Потому что я хочу убедиться, что использую функцию atof из глобального пространства имен.
TimW
1
зависит от текущей локали
nmr
104
Стандартная библиотека (C ++ 11) предлагает желаемые функции с std::stod:
std::string s ="0.6"
std::wstring ws ="0.7"double d = std::stod(s);double dw = std::stod(ws);
Обычно для большинства других основных типов см. <string> . Также есть некоторые новые функции для строк C. Видеть<stdlib.h>
Мне нравится это решение, но похоже, что оно только из C ++ 11. Так что недоступно в моем SDK.
pamplemousse_mk2
Это здорово знать , что комитет по стандартизации C ++ добавил это. ostringstreamсам по себе был слишком длинным, чтобы печатать, не говоря уже об использовании ..
bobobobo
4
Для чисел с плавающей запятой (как задано в вопросе, который я нашел с помощью Google, набрав «c ++ string to float»), следует использовать std :: stof.
Étienne
1
Замечу, что это может вызвать исключения: std :: invalid_argument (если преобразование не удалось) std :: out_of_range (если вне диапазона)
Джейсон Дусетт,
3
Покупатель, будьте осторожны, это зависит от текущего региона.
Спасибо, работает .. Но это вопрос ко мне: почему мой код не работает.
Макс Фрай,
2
@Johannes Schaub: Основываясь на ADL, он мог бы с таким же успехом иметь, определения using плюс то, что он фактически использует, вероятно, внесет в область применения огромное количество элементов std. Кроме того, lexical_cast безумно медленный, так что +1 от меня нет.
Приятной особенностью boost :: lexical_cast является обработка ошибок. Если преобразование не удается, try { ... boost::lexical_cast ... } catch (std::exception const& err) { //handle excpetion }
выдается
Чтобы быть более точным, используйте catch ( boost::bad_lexical_cast const& err )для перехвата исключения.
Semjon Mössinger
14
Вы можете использовать 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;}
Эээ, вы думаете, что у boost :: lexical_cast ужасный интерфейс, не так ли? Посмотрите ответ stefanB! Boost делает то же самое.
kirsche40
@ kirsche40 Кажется хорошей альтернативой для людей, у которых еще нет зависимостей от Boost (связывание с Boost только для преобразования std :: string в числа - это немного излишне!)
Жан-Филипп Жоден
@ JEan-Phillippe Jodiun Я ответил на теперь удаленный комментарий, где кто-то рекомендовал Boost. Я знаю, что Boost в большинстве случаев является излишним. Кстати, с некоторых пор использование Boost ограничено «более новыми» компиляторами. В более старых проектах нельзя использовать Boost. Например, ASIO сильно зависит от функций C ++ 11, таких как std :: addressof, что делает его совершенно бесполезным для компиляторов C ++ 98 / C ++ 03. ИМХО, когда проект стартовал, намерением Boost было предоставить новые "стандартизованные" функции для старых версий компилятора ... :-(
kirsche40
10
Да, с лексическим составом. Используйте строковый поток и оператор << или используйте Boost, они уже реализовали его.
Ваша собственная версия может выглядеть так:
template<typename to,typename from>to lexical_cast(from const&x){
std::stringstream os;
to ret;
os << x;
os >> ret;return ret;}
Примечание: boost :: lexical_cast вызывает исключение, поэтому вы должны быть готовы с ним справиться, когда вы передаете недопустимое значение, попробуйте передать строку ("xxx")
Неверный ответ, откуда вы знаете, что значение, хранящееся в num, на самом деле является действительным числом с плавающей запятой? вы не проверяете возвращаемый тип sscanf, похоже на стиль кодирования MS.
1
Этот ответ подкреплен вашими комментариями. У меня есть глубокие подозрения, что вы просто неправильно показываете результат.
Однажды со мной случилось то же самое. Я потратил целый день, пытаясь понять, почему я получил плохое значение в 64-битном int, только чтобы обнаружить, что printf игнорирует второй байт. Вы не можете просто передать 64-битное значение в printf, как int.
Я не использую printf для просмотра результатов ... И я использую это значение для установки непрозрачности окна, и мое окно полностью прозрачное, поэтому значение равно 0.
Макс Фрай
1
Способ C ++ 11 - использовать std :: stod и std :: to_string. Оба работают в Visual Studio 11.
Что касается того, почему atof()не работает в исходном вопросе: тот факт, что он приведен к удвоению, вызывает у меня подозрения. Код не должен компилироваться без него #include <stdlib.h>, но если приведение было добавлено для устранения предупреждения компиляции, atof()оно объявлено неправильно. Если компилятор предполагает, что atof()возвращает int, его приведение устранит предупреждение о преобразовании, но не приведет к тому, что возвращаемое значение будет распознано как двойное.
#include<stdlib.h>#include<string>...
std::string num ="0.6";double temp = atof(num.c_str());
В любом случае вам не нужно Boost lexical_cast для строки <-> с плавающей запятой. Это подмножество вариантов использования - единственный набор, для которого ускорение постоянно хуже, чем у старых функций, и они в основном сосредоточили все свои отказы именно там, потому что их собственные результаты производительности показывают производительность в 20-25 раз МЕДЛЕННУЮ, чем при использовании sscanf и printf для таких преобразований.
Погуглите сами. boost :: lexical_cast может обрабатывать примерно 50 преобразований, и если вы исключите те, которые включают #s с плавающей запятой, это будет так же хорошо или лучше, как и очевидные альтернативы (с дополнительным преимуществом наличия единого API для всех этих операций). Но добавьте поплавки, и это похоже на то, что Титаник врезался в айсберг с точки зрения производительности.
Все старые специализированные функции str-> double могут выполнять 10000 разборов примерно за 30 мс (или лучше). lexical_cast занимает примерно 650 мс, чтобы выполнить ту же работу.
Строка, не зависящая от локали, в двойную (десятичный разделитель всегда '.
Обнаружение ошибки при сбое преобразования строки
Мое решение (использует функцию 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 ... мне потребовалось довольно много времени, чтобы добраться до этого решения. И у меня до сих пор такое чувство, что я недостаточно разбираюсь в локализации строк и тому подобном ...
Ответы:
Для меня это правильный синтаксис C ++ для преобразования строки в double.
Вы можете сделать это с помощью stringstream или boost :: lexical_cast, но это снижает производительность.
Ахаха, у вас есть проект Qt ...
Дополнительное примечание:
если входные данные - это
const char*
,QByteArray::toDouble
будет быстрее.источник
Стандартная библиотека (C ++ 11) предлагает желаемые функции с
std::stod
:Обычно для большинства других основных типов см.
<string>
. Также есть некоторые новые функции для строк C. Видеть<stdlib.h>
источник
ostringstream
сам по себе был слишком длинным, чтобы печатать, не говоря уже об использовании ..Лексический состав очень приятный.
источник
try { ... boost::lexical_cast ... } catch (std::exception const& err) { //handle excpetion }
catch ( boost::bad_lexical_cast const& err )
для перехвата исключения.Вы можете использовать std :: stringstream:
Использование:
источник
Да, с лексическим составом. Используйте строковый поток и оператор << или используйте Boost, они уже реализовали его.
Ваша собственная версия может выглядеть так:
источник
Вы можете использовать усиление лексического приведения:
Примечание: boost :: lexical_cast вызывает исключение, поэтому вы должны быть готовы с ним справиться, когда вы передаете недопустимое значение, попробуйте передать строку ("xxx")
источник
Если вы не хотите перетаскивать все ускорение, используйте
strtod(3)
from<cstdlib>
- он уже возвращает двойное значение.Выходы:
Почему atof () не работает ... на какой платформе / компиляторе вы работаете?
источник
У меня была такая же проблема в Linux
оно работает.
источник
источник
Этот ответ подкреплен вашими комментариями. У меня есть глубокие подозрения, что вы просто неправильно показываете результат.
Однажды со мной случилось то же самое. Я потратил целый день, пытаясь понять, почему я получил плохое значение в 64-битном int, только чтобы обнаружить, что printf игнорирует второй байт. Вы не можете просто передать 64-битное значение в printf, как int.
источник
Способ C ++ 11 - использовать std :: stod и std :: to_string. Оба работают в Visual Studio 11.
источник
Что касается того, почему
atof()
не работает в исходном вопросе: тот факт, что он приведен к удвоению, вызывает у меня подозрения. Код не должен компилироваться без него#include <stdlib.h>
, но если приведение было добавлено для устранения предупреждения компиляции,atof()
оно объявлено неправильно. Если компилятор предполагает, чтоatof()
возвращает int, его приведение устранит предупреждение о преобразовании, но не приведет к тому, что возвращаемое значение будет распознано как двойное.должен работать без предупреждений.
источник
Вместо того, чтобы перетаскивать Boost в уравнение, вы можете оставить свою строку (временно) как a
char[]
и использоватьsprintf()
.Но, конечно, если вы все равно используете Boost, это не такая уж большая проблема.
источник
В любом случае вам не нужно Boost lexical_cast для строки <-> с плавающей запятой. Это подмножество вариантов использования - единственный набор, для которого ускорение постоянно хуже, чем у старых функций, и они в основном сосредоточили все свои отказы именно там, потому что их собственные результаты производительности показывают производительность в 20-25 раз МЕДЛЕННУЮ, чем при использовании sscanf и printf для таких преобразований.
Погуглите сами. boost :: lexical_cast может обрабатывать примерно 50 преобразований, и если вы исключите те, которые включают #s с плавающей запятой, это будет так же хорошо или лучше, как и очевидные альтернативы (с дополнительным преимуществом наличия единого API для всех этих операций). Но добавьте поплавки, и это похоже на то, что Титаник врезался в айсберг с точки зрения производительности.
Все старые специализированные функции str-> double могут выполнять 10000 разборов примерно за 30 мс (или лучше). lexical_cast занимает примерно 650 мс, чтобы выполнить ту же работу.
источник
Моя проблема:
Мое решение (использует функцию Windows _wcstod_l):
HTH ... мне потребовалось довольно много времени, чтобы добраться до этого решения. И у меня до сих пор такое чувство, что я недостаточно разбираюсь в локализации строк и тому подобном ...
источник