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

RusFAQ.ru: Программирование на языке Pascal


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

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

Выпуск № 172
от 22.05.2006, 20:35

Администратор:Калашников О.А.
В рассылке:Подписчиков: 184, Экспертов: 48
В номере:Вопросов: 1, Ответов: 4


Вопрос № 43396: Здравствуйте, уважаемые эксперты! Прошу помощи в "детском" вопросе. Вот такая есть программка (точнее, та выжимка, которая не работает как надо в другой программе) --- program tabul; var x,y: real; Begin x:=...

Вопрос № 43.396
Здравствуйте, уважаемые эксперты!
Прошу помощи в "детском" вопросе.
Вот такая есть программка (точнее, та выжимка, которая не работает как надо в другой программе)
---
program tabul;
var
x,y: real;
Begin
x:=-1;
repeat
if x<3 then y:=2
else
y:=4;
if x=3 then y:=5;
writeln ('x= ',x,' y= ',y);
x:=x+0.2;
until (x>5);
readln;
End.
Ребенок спрашивает, почему при шаге 0.5 и 0.25 в цикле получаются одни результаты, а при шаге 0.2 - совершенно другой? (строка x:=x+0.2;)
А я не знаю, в чем тут тонкость, ибо ошибок вроде нет, тип переменных менять пробовали... Т.е. получается, что при шаге 0.2 почему-то нет X=3 или выплывает где-то мизерная погрешность (где?!). Пробовали и разные конструкции операторов If, и цикл While - все равно вылет именно на этой точке! Так в чем же дело, никак не пойму!
(кстати, еще при шаге 0.1 тоже врет, но в другую сторону)
Спасите, пожалуйста, от вскипания мозгов (или того, что у меня вместо них)!!
Отправлен: 17.05.2006, 20:26
Вопрос задала: Shapoklak (статус: Профессор)
Всего ответов: 4
Мини-форум вопроса >>> (сообщений: 1)

Отвечает: Ерёмин Андрей
Здравствуйте, Shapoklak!
Теоретически, здесь всё правильно. Но не совсем. Всё дело в типах. В данном случае, если сравнивать 3 и 3.00000... - то это получаются две разные вещи. Поэтому, вам следует округлить real-число, либо взять его целую часть. Например, если заменить условие так: if int(x)=3 then y:=5;, то вы на выходе получите значение y = 5 в пяти строчках (3.0, 3.2, 3.4, 3.6, 3.8). Как правильно реализовать это сходство - оставляю вам на размышление :-) Надеюсь, система понятна.
---------
Нет правила без исключений. Правило без исключений - исключение из правил.
Ответ отправил: Ерёмин Андрей (статус: Профессор)
Россия, Тула
WWW: Программирование на DELPHI: Всё для программиста.
ICQ: 286837644
----
Ответ отправлен: 17.05.2006, 20:51
Оценка за ответ: 5
Комментарий оценки:
Да, все понятно. Спасибо большое.

Отвечает: Устинов Сергей Евгеньевич
Здравствуйте, Shapoklak!
Проблема в том, что точность типа real 11-12 знаков, т.е. во всех знаках дальше программа может ошибаться. Именно это и происходит в Вашей программе. Для того, чтобы обойти можно воспользоваться таким методом:
if int(x*100)=300 then y:=5
(но думаю ребенку объяснить это будет не совсем просто)
Удачи!!!
---------
Ответы на все вопросы - на сайте www.ya.ru :)
Ответ отправил: Устинов Сергей Евгеньевич (статус: 9-ый класс)
Ответ отправлен: 17.05.2006, 21:25
Оценка за ответ: 5
Комментарий оценки:
Спасибо.

Отвечает: Сухомлин Кирилл Владимирович
Здравствуйте, Shapoklak!
Хотел дополнить.
Все правильно, сравнивать нельзя из-за округления.
Но почему все нормально для шагов 0.5 и 0.25?
Потому, что в программе, хотя вы и оперируете числами в десятичном формате, но реальное представление в памяти (в регистрах, во всём) - двоичное. А 1/5 в двоичном представление - периодическая дробь. Аналогия: попробуйте вычислить (1/3) + (2/3) на неинженерном калькуляторе - получите 0.99999...
Или то же самое даже на компьютере:
WriteLn(1/3 + 2/3);
А (1/4) + (3/4) всегда равно 1. Если, конечно, у калькулятора не 2 разряда ;-)

Приложение:

Ответ отправил: Сухомлин Кирилл Владимирович (статус: 5-ый класс)
Ответ отправлен: 17.05.2006, 21:37
Оценка за ответ: 5
Комментарий оценки:
Действительно! И правда! Да конечно с тем, что такие погрешности есть, я сталкивалась многократно, но обычно ими можно было пренебречь, а тут такая программа, что это влияет, можно сказать, катастрофическим образом! Я думаю, авторы задачника вряд ли предполагали такой результат (в ответах текст примерно как приведенный) - наверное, не проверяли конечный результат на практике.
А какая великолепная иллюстрация ко многим темам...

Отвечает: Sarymian
Здравствуйте, Shapoklak!

Измените строку
writeln ('x= ',x,' y= ',y);

на строку
writeln ('x= ',x:2:2,' y= ',y:2:2);

Увидите отличие в отображение "Реальных" чисел.
Т.к. вы обьявили тип real то числа у вас отображаются как -1,(ля-ля тополя, т.е не целая часть)E+00А если поставить Х:3:2 то у вас будут отображатся только 3 знака до запятой и 2 знака после, т.е. более приятный вид отображения числа.
Ответ отправил: Sarymian (статус: 2-ой класс)
Ответ отправлен: 18.05.2006, 06:36


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

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

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

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

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


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


© 2001-2006, Портал RusFAQ.ru, Россия, Москва.
Идея, дизайн, программирование: Калашников О.А.
Email: adm@rusfaq.ru, Тел.: +7 (926) 535-23-31
Авторские права | Реклама на портале
Версия системы: 4.32 от 03.05.2006
Яндекс Rambler's Top100

В избранное