Я задаюсь вопросом, какой алгоритм может быть использован, чтобы взять что-то вроде «4.72» в тип данных с плавающей точкой, равныйстрока для преобразования плавающего?
float x = 4.72;
Я задаюсь вопросом, какой алгоритм может быть использован, чтобы взять что-то вроде «4.72» в тип данных с плавающей точкой, равныйстрока для преобразования плавающего?
float x = 4.72;
scanf
, operator>>
для istreams и strtof
- это очевидный выбор.
Там это также atof
, но, как atoi
, ему не хватает способ сказать вам произошла ошибка на входе, так что, как правило, лучше избегать обоих.
+1 для 'strtof'. –
В atof() функция может быть полезной. http://www.cplusplus.com/reference/clibrary/cstdlib/atof/
Я настоятельно рекомендую 'strtod()' over 'atof()', поскольку у вас есть больше шансов узнать, что что-то пошло не так, когда вы получаете неожиданный ввод с помощью 'strtod()'. – RBerteig
Совершенно верно. Согласен. –
Для C
strtod()
и C99
друзей strtof()
и strtold()
(описание на той же ссылке) уже есть, что алгоритм реализован.
Если у вас возникли проблемы с написанием собственного сообщения, напишите свой код и задайте ему конкретные вопросы.
'strtof' вместо' strtod', так как вопрошающий хочет 'float' вместо' double'. –
Правый Стивен, спасибо (но strtof и strtold являются «новыми»). Сообщение отредактировано. – pmg
Использование 'strtod' и преобразование результата в' float' (неявно или с литой) является столь же хорошим и более переносимым, чем 'strtof'. –
Вы можете использовать импульс: lexical_cast
http://www.boost.org/doc/libs/1_44_0/libs/conversion/lexical_cast.htm
Для C++ вы можете использовать boost::lexical_cast:
std::string str("4.72");
float x = boost::lexical_cast<float>(str);
Для C вы можете использовать sscanf:
char str[]= "4.72";
float x;
sscanf(str, "%f", &x);
Для C++ This это алгоритм, который я использую:
bool FromString(const string& str, double& number) {
std::istringstream i(str);
if (!(i >> number)) {
// Number conversion failed
return false;
}
return true;
}
Я использовал atof() в прошлом для преобразования, но я нашел это проблематичным, потому что если действительное преобразование не может быть выполнено, оно вернется (0.0). Таким образом, вы не знали бы, не сработали ли они и вернули нуль, или если в строке действительно было «0».
От cplusplus.com: «stringstream
предоставляет интерфейс для управления строками, как если бы они были потоками ввода/вывода».
Вы можете инициализировать stringstream
с вашей строки, то читать поплавок из stringstream
используя operator>>
так же, как вы бы с cin
.
Вот пример:
#include<iostream>
#include<string>
#include<sstream>
using namespace std;
int main() {
string s = "4.72";
stringstream sstrm(s);
float x;
sstrm >> x;
cout << x << endl;
}
Я предполагаю, что вы хотите, фактический алгоритм, а не функция библиотеки, которая уже делает это. У меня нет времени, чтобы написать и проверить фактический код, но вот то, что я хотел бы сделать:
Из-за округления преобразования между базой 10 и базой 2 на каждой итерации этого цикла результат, полученный из этого алгоритма, может быть не самым близким бинарным представлением к исходному значению. Я действительно не знаю, как улучшить его, хотя ... возможно, кто-то еще может это сделать.
Не забудьте обработать цифры типа '-1.2e-3'. Это преобразование чревато тонкостями и краевыми случаями. Это отнюдь не просто, чтобы получить право. Если вы должны реализовать его самостоятельно, проверьте дерьмо из него на каждом краевом кейсе, о котором вы можете мечтать. А потом волнуйся. И не забывайте также о случаях NaN и INF. – RBerteig
@RBerteig: если это моя функция преобразования строк, я могу просто объявить отрицательные числа и научную нотацию недействительными;) Но на самом деле, да, это должно быть более сложным, чем то, что я написал. Я подумал, что ОП просто пытается обернуть вокруг, как такое преобразование возможно. – rmeador
Конечно, вы можете принять решение о разумных пределах для того, что должно быть обработано для упрощения проблемы. Я просто подумал, что добавлю напоминание о том, что преобразование текста в плавающую точку, возможно, придется обрабатывать случаи, более сложные, чем «4.72». Одна реализация C89-совместимого 'strtod()' я видел, например, около 80 строк плотного и едва прокомментированного кода. – RBerteig
Как вы просили алгоритм, а не метод, вот мое объяснение для простого алгоритма (и реализация в C):
Думаю, чтение кода может быть проще. Итак, вот код:
float atof(char *s)
{
int f, m, sign, d=1;
f = m = 0;
sign = (s[0] == '-') ? -1 : 1;
if (s[0] == '-' || s[0] == '+') s++;
for (; *s != '.' && *s; s++) {
f = (*s-'0') + f*10;
}
if (*s == '.')
for (++s; *s; s++) {
m = (*s-'0') + m*10;
d *= 10;
}
return sign*(f + (float)m/d);
}
Приятное и понятное объяснение с источником для простой части. Не забудьте обработать '-1e-6',' .3e + 5', '+ 2.e-4' и т. Д. Или указать явно, что вы не разрешаете эту форму. Подумайте о том, как лучше обрабатывать неверные числа (попробуйте «ABC» в качестве входных данных). Также рассмотрите обработку NaN и INF. C99 требует, чтобы 'scanf()' был способен точно восстановить значение, напечатанное 'printf()', даже NaN и INF. C89 не делает, но его 'strtod()' выполняет дескриптор 'E'. – RBerteig
Вы действительно хотите * алгоритм * или просто функцию, которая уже написана? – fennec