Отправляет email-рассылки с помощью сервиса Sendsay
  Все выпуски  

RusFAQ.ru: Программирование на C / C++


РАССЫЛКИ ПОРТАЛА RUSFAQ.RU

/ КОМПЬЮТЕРЫ И ПО / Языки программирования / C/C++

Выпуск № 845
от 10.09.2007, 19:35

Администратор:Калашников О.А.
В рассылке:Подписчиков: 500, Экспертов: 71
В номере:Вопросов: 2, Ответов: 7


Вопрос № 100843: здраствуйте эксперты. Программирую на VS2005. При выполнении следующего кода выводится неожиданый результат. char string[] = "-4.7128"; float flnumber = atof(string); После выполнения данного кода переменная flNumb...
Вопрос № 100968: Необходимо организовать переход между текстовыми файлами. После запуска программы на экран выводится содержимое первого файла, как только программа обнаруживает конец первого файла, происходит очистка поля и выводится содержимое второго файла. Так до...

Вопрос № 100.843
здраствуйте эксперты.
Программирую на VS2005. При выполнении следующего кода выводится неожиданый результат.

char string[] = "-4.7128";
float flnumber = atof(string);

После выполнения данного кода переменная flNumber == -471279999
Как сделать чтобы строка преобразовалась правильно
Отправлен: 04.09.2007, 20:58
Вопрос задал: Sulimacom (статус: Посетитель)
Всего ответов: 5
Мини-форум вопроса >>> (сообщений: 11)

Отвечает: Виктор Пырлик
Здравствуйте, Sulimacom!

Вот код:

#include
#include
#include
#include
//------------------------------------------------
int _tmain(int argc, _TCHAR* argv[])
{
char string[] = "-4.7128";
float flnumber = atof(string);
printf("result: %f",flnumber);
getch();
return 0;
}


результат:
result: -4.712800

Как видите, всё нормально. Строки я скопировал с вашего вопроса.
Но.. можете использовать тип double.

PS: среда - VS2005.

---------
Если ничего не помогло - надо читать инструкцию
Ответ отправил: Виктор Пырлик (статус: Студент)
Ответ отправлен: 04.09.2007, 21:25

Отвечает: Maxim V.G.
Здравствуйте, Sulimacom!

Если использовать тип float то на 1000 итераций возникает погрешность. А исспользуя тип double погрешности нет.
double flnumber_ = 0;
double flnumber;
char string[] = "-4.7128";
for (int i = 0; i<1000001; i++){
flnumber = atof(string);
flnumber_ = flnumber * i;
printf("result: %f*%d=%f ",flnumber,i,flnumber_);
}

result: -4.7128*1000000=4712800

А с типом float на третей итерации даёт сбой.

Отсюда вывод: надо использовать тип double!!!
---------
Жить вредно - от неё умирают
Ответ отправил: Maxim V.G. (статус: 4-ый класс)
Ответ отправлен: 05.09.2007, 02:00
Оценка за ответ: 4
Комментарий оценки:
переделал свой код для работы с типом double но переменная преобразуется не коректно. Дебагер показывает x -4.7127999999999997 double

Отвечает: Aristos
Здравствуйте, Sulimacom!

Строка преобразуется правильно. Все дело в том, что числа с плавающей точкой имеют ограниченную точность. Так переменная с типом float имеет 7 значащих знаков, с типом double (двойная точность) - 15 знаков. Поэтому не стоит удивляться тому, что 4.71279999f будет равно 4.7128f . Стоит отметит способ задания типа у числовых констант (чтобы различить float и double). В обычной записи (4.7128) тип константы будет double, чтобы указать, что константа имеет тип float необходимо в конце числа приписать символ f. А константы без десятичной точки будут иметь целочисленные типы. Например:

4.7128 - double
4.7128f - float
4 - int или short или char
4. - double
4.f - float

Следует избегать в коде сравнение на равенство/неравентсво переменых нецелочисленных типов. Отношения больше/меньше работают вполне корректно. И не стоит забывать про типы у констант.

Приложение:

Ответ отправил: Aristos (статус: 5-ый класс)
Ответ отправлен: 05.09.2007, 11:44
Оценка за ответ: 3
Комментарий оценки:
Как применить ваш ответ в моём примере

Отвечает: Rockie
Здравствуйте, Sulimacom!

При вычислениях с плавающей точкой в любом случае будет погрешность. Каков результат деления 10/3? На бумаге вы можете записать 3.(3), но в компьютере это число непредставимо, так как количество битов для представления числа конечно.

Могу предложить вам запоминать количество знаков после запятой в строке, а потом округлять полученный результат по этому значению(то есть округлять 4.71279 к 4.7128). Функции округления есть в сети(последние 3 ссылки).

Ссылки по теме:

http://forum.sources.ru/index.php?showtopic=139331&hl=setprecision
http://forum.sources.ru/index.php?showtopic=138808&view=showall
http://forum.vingrad.ru/faq/topic-157825.html
http://forum.sources.ru/index.php?showtopic=67207
http://forum.ixbt.com/topic.cgi?id=40:399
Ответ отправил: Rockie (статус: 3-ий класс)
Ответ отправлен: 06.09.2007, 00:22

Отвечает: Зелик Колабухин
Здравствуйте, Sulimacom!

Этот результат вполне ожиданный. Вы можете программировать хоть на паскале хоть на C# - везде одно и тоже. А все дело в стандарте IEEE754 на хранение и обработку чисел типа float. Примерно этот стандарт можно описать так: все числа хранить в удобном для процессора виде. Т.е. числа хранятся в памяти таким образом, чтобы потом с ними процессор мог быстро производить нужные операции. Соответственно число "-4.7128" плохое, а число близкое к нему "-471279999..." - хорошее для работы процессора.
К сожалению этому ни где не учат, когда знакомят с форматом float и поэтому очень часто программист не может понять почему правильно написанная программ начинает глючить.
Так что у меня совет один: пользуйся флоатом только в случае крайней необходимости, иначе можешь на ровном месте зависнуть и на долго. А лучше всего - - забудь, что такой тип есть.

По указанному стандарту только что нашел статью:
"IEEE754-тика угрожает человечеству"
например по адресу http://www.yur.ru/science/computer/IEEE754.htm

Цитата из этой статьи:
"Взрыв ракеты "Пэтриот» в Саудовской Аравии 25 февраля 1991, который привел к гибели 28 человек, связан с ошибками округления."

Ответ отправил: Зелик Колабухин (статус: 3-ий класс)
Ответ отправлен: 06.09.2007, 10:34


Вопрос № 100.968
Необходимо организовать переход между текстовыми файлами. После запуска программы на экран выводится содержимое первого файла, как только программа обнаруживает конец первого файла, происходит очистка поля и выводится содержимое второго файла. Так должно продолжаться до тех пор, пока программа не переберет все имеющиеся текстовые файлы.

Причем все файлы имеют схожие названия такого типа: question_1.txt, question_2.txt, question_3.txt

Как примерно должен выглядеть программный код. Буксую на одном месте. Помогите, пожалуйста!
Отправлен: 05.09.2007, 19:12
Вопрос задала: Stacey_campbell (статус: Посетитель)
Всего ответов: 2
Мини-форум вопроса >>> (сообщений: 1)

Отвечает: Sov
Здравствуйте, Stacey_campbell!
Пример для билдера

Приложение:

Ответ отправил: Sov (статус: 6-ой класс)
Ответ отправлен: 05.09.2007, 20:55

Отвечает: Терсков Сергей
Здравствуйте, Stacey_campbell!
Очень похоже га ваш же вопрос № 100831. В моем ответе приведен подобный код с использованием STL. Если имена файлов схожи, то остается только генерировать их в цикле. То есть нужен будет код подобный этому:

См приложение.

Приложение:

Ответ отправил: Терсков Сергей (статус: Студент)
Ответ отправлен: 06.09.2007, 03:29


Отправить вопрос экспертам этой рассылки

Приложение (если необходимо):

* Код программы, выдержки из закона и т.п. дополнение к вопросу.
Эта информация будет отображена в аналогичном окне как есть.

Обратите внимание!
Вопрос будет отправлен всем экспертам данной рассылки!

Для того, чтобы отправить вопрос выбранным экспертам этой рассылки или
экспертам другой рассылки портала RusFAQ.ru, зайдите непосредственно на RusFAQ.ru.


Форма НЕ работает в почтовых программах The BAT! и MS Outlook (кроме версии 2003+)!
Чтобы отправить вопрос, откройте это письмо в браузере или зайдите на сайт RusFAQ.ru.


© 2001-2007, Портал RusFAQ.ru, Россия, Москва.
Авторское право: ООО "Мастер-Эксперт Про"
Техподдержка портала, тел.: +7 (926) 535-23-31
Хостинг: "Московский хостер"
Поддержка: "Московский дизайнер"
Авторские права | Реклама на портале
Версия системы: 4.58 от 30.08.2007
Яндекс Rambler's Top100
RusFAQ.ru | MosHoster.ru | MosDesigner.ru | RusIRC.ru
Kalashnikoff.ru | RadioLeader.ru | RusFUCK.ru

В избранное