Как я могу проверить, может ли строка быть преобразована в число с плавающей запятой?
Автор вопроса: LotharОтветов: 7
Во-первых, мой контекст - это контекст автора компилятора, которому нужно преобразовать литералы с плавающей запятой (строки) в значения с плавающей запятой/двойные числа. Я не занимался программированием с плавающей запятой последние 15 лет, поэтому я почти уверен, что это совершенно глупый вопрос новичка.
но в библиотеке времени выполнения c нет функции "strtof"?
РЕДАКТИРОВАТЬ: Чтобы уточнить. Я уже знаю, что строка 'literal' является допустимым шаблоном для числа C с плавающей запятой. Он уже прошел проверку регулярными выражениями. Я просто хочу проверить, есть ли проблема с диапазоном/точностью.
Причина в исходном коде Eiffel, который пользователь может написать
a := {REAL_32} 3.1415
b := {REAL_32} 3.0E200
Чтобы преобразовать записанное число с плавающей запятой в 32-битное число с плавающей запятой. Думаю, во втором случае компилятор должен определить, что значение выходит за пределы допустимого диапазона, и выдать ошибку или хотя бы предупреждение.
Почему вам нужно, чтобы это было число с плавающей точкой, а не двойное? 20.12.2009
Я думаю, вы должны преобразовать свой литерал в двойной. Затем приступайте к актерскому составу. Во время каста вы должны проверить, находится ли двойное значение в пределах диапазона с плавающей запятой. 21.12.2009
Вам может понадобиться или не понадобиться добавить тест для правильного возврата strtod(), в зависимости от того, есть ли возможность переполнения в типе double.
Ответ 2 · рейтинг 9 · Community
В C89 вы можете использовать sscanf.
Например:
float myfloat;
if(sscanf(str, "%f", &myfloat) != 1)
/* String could not be converted */
else
/* String was converted, myfloat is usable */
Ответ 3 · рейтинг 6 · jamesdlin
@ Николас Гой: я не думаю, что sscanf(str, "%f, &float) == 1 (или != 1) действительно делает то, что нужно.
Если в str есть дополнительные символы (например, "1.1foo"), он будет парсить без ошибок, что, вероятно, нежелательно. Это можно исправить, выполнив:
вместо. Тем не менее, sscanf с %f, скорее всего, будет использовать strtod внутренне и все равно будет приведено к float. Язык в стандарте C говорит:
a,e,f,g Соответствует необязательному знаковому числу с плавающей запятой, бесконечности или NaN, формат которого совпадает с ожидаемым для последовательности субъектов функции strtod. Соответствующий аргумент должен быть указателем на плавающий.
что подразумевает это, и это кажется правдой для меня (gcc 4.2.1 на FreeBSD). Используя приведенный выше код sscanf, "1.79e308" анализируется успешно, но имеет значение +inf, как и "5e-300" со значением 0.0, и это те же результаты, которые вы получили бы от (float) 1.79e308 и (float) 5e-300.
Так или иначе. Все сказанное, я задаюсь вопросом, почему OP все равно хочет использовать float вместо double.
Ответ 4 · рейтинг 5 · Community
Я хотел сказать, просто используйте код, который у вас уже есть, но присвойте результат strod() веществу с плавающей запятой, а не двойному. Но ваш код неверен по нескольким причинам.
Во-первых, вы не можете проверить errno, если не произошла ошибка. Во-вторых, strtod() не будет устанавливать errno, за исключением таких вещей, как ошибки диапазона. Если вы передадите ему недопустимый номер, например "XYZ", он не будет установлен.
Более правильное использование strtod:
char *p;
double d = strtod( "123.4xyz", & p );
if ( * p != 0 ) {
// not a number - in this case will point at 'x'
}
Используя strtod() для чтения числа с плавающей запятой, вы можете потерять некоторую точность, но это цена, которую вы платите за использование числа с плавающей запятой - в общем, если у вас нет очень веской причины не делать этого, вы всегда должны предпочитать использование числа с плавающей запятой.
Ответ 5 · рейтинг 4 · Thomas
strtof не существует в C89, но есть в C99.
Ответ 6 · рейтинг 4 · Pavel Radzivilovsky
Я предлагаю сначала преобразовать в double, а затем перевести в float. Если относительная разница (f-d)/f больше, чем точность числа с плавающей запятой (примерно 1e-7), то цифр больше, чем можно безопасно хранить в числе с плавающей запятой.
Ответ 7 · рейтинг 2 · Hans Passant
В MSVC вы можете использовать _atoflt(), определенный в stdlib.h