Сейчас на форуме: hgdagon, asfa, bartolomeo (+6 невидимых)

 eXeL@B —› Программирование —› косяк в pascal'e(и в Delphi)
Посл.ответ Сообщение

Ранг: 260.2 (наставник)
Активность: 0.190
Статус: Участник

Создано: 20 октября 2006 06:00
· Личное сообщение · #1

[HIGHLIGHT=pascal]
program XXX;
Var
a,b,h:real;
begin
a:=0.5;
b:=0.8;
h:=0.05;
while a<=b do
begin
writeln(a:0:2);
a:=a+h;
end;
readln;
end.
[/HIGHLIGHT]

По логике он должен вывести 7 чисел: 0.50 0.55 0.60 0.65 0.70 0.75 0.80;
Т.к написано a<=b (а 0,8=0,8)

А он выводит 6 чисел ( не выводит 0,8)
На Delphi такая же фигня.

Но если написать a:=5; b:=8; c:=0.5 то всё выводится правильно.
В чём трабла?



Ранг: 160.1 (ветеран)
Активность: 0.070
Статус: Участник

Создано: 20 октября 2006 06:15
· Личное сообщение · #2

sniperZ пишет:
В чём трабла?

в точности представления чисел с плавающей точкой.
0.8 нельзя представить точно, поэтому равенство не выполняется. Кури доки по работе с вещественными числами.



Ранг: 260.2 (наставник)
Активность: 0.190
Статус: Участник

Создано: 20 октября 2006 06:34 · Поправил: sniperZ
· Личное сообщение · #3

infern0 пишет:
Кури доки по работе с вещественными числами.


Я не курю.

Про нашёл косяк.

Кстати, из-за него я проиграл чашку кофе Nescafe (из автомата).



Ранг: 45.1 (посетитель)
Активность: 0.030
Статус: Участник

Создано: 20 октября 2006 06:50
· Личное сообщение · #4

Нельзя сравнивать вещетвенные числа после операций над ними.
infern0 все правильно сказал.

но вот такая фигня работать будет:

Var
a,b,h: extended;
d,e: single;

begin
a:=0.5;
b:=0.8;
h:=0.05;

d:=a;
e:=b;

while d<=e do
begin
writeln(a:0:2);
a:=a+h;
d:=a;
end;
readln
end;




Ранг: 310.8 (мудрец), 29thx
Активность: 0.430
Статус: Участник

Создано: 21 октября 2006 01:02
· Личное сообщение · #5

sniperZ пишет:
Про нашёл косяк.

Косяк в том, что машинная арифметика не тождественна математической.
В т.ч. иногда b != a+(b-a) и a+b+c != c+b+a



Ранг: 253.9 (наставник)
Активность: 0.130
Статус: Участник

Создано: 21 октября 2006 01:35
· Личное сообщение · #6

вот уж как бывает... на этом можно собаку съесть... теперь буду знать.

-----
MicroSoft? Is it some kind of a toilet paper?




Ранг: 2.0 (гость)
Активность: 0=0
Статус: Участник

Создано: 21 октября 2006 02:09
· Личное сообщение · #7

В большинстве случаев лучше пользоваться целочисленной арифметикой, например:

program XXX;
Var
a,b,h,x:real;
i,n:integer;
begin
a:=0.5;
b:=0.8;
h:=0.05;
n:=(b-a)/h;
for i:=0 to n do
begin
x:=a+i*h;
writeln(x:0:2);
end;
readln;
end.

Но и это ещё не всё. Если Вы работаете на PC-платформе, то начиная с пентиумов выгоднее стало использовать вместо типов Real и Integer типы Extended и LongInt. Это связано с тем, что на этих компьютерах все вычисления всё равно проводятся в Extended и LongInt при использовании в программе иных типов операция копирования превращается в операцию преобразования типов, что само по себе требует времени. (Скорость вычислений сопроцессора соизмерима со скоростью исполнения инструкций центральным процессором).
Я знаю два случая, когда это не работает:
1) когда необходимо хранить и обрабатывать огромные массивы данных и важен размер каждого элемента - экономия.
2) Использование готовых (как правило старых) подпрограмм с иными типами данных - совместимость.



Ранг: 163.7 (ветеран)
Активность: 0.070
Статус: Участник

Создано: 21 октября 2006 04:33
· Личное сообщение · #8

xDriver пишет:
Нельзя сравнивать вещетвенные числа после операций над ними


В Дельфи, возможно, да. Если там нет DBL_EPSILON или numeric_limits::epsilon().



Ранг: 310.8 (мудрец), 29thx
Активность: 0.430
Статус: Участник

Создано: 01 ноября 2006 05:01
· Личное сообщение · #9

S_T_A_S_ пишет:
Если там нет DBL_EPSILON

Так это просто константа для использования. Ее наличие не спасает, просто надо писать что-то типа
a<=b+DBL_EPSILON
Но если складывать много чисел или много раз, то все равно надо будет думать и считать.
DBL_EPSILON пришло из стандарта Си.
float.h
#define DBL_EPSILON 2.2204460492503131e-016 /* smallest such that 1.0+DBL_EPSILON != 1.0 */


 eXeL@B —› Программирование —› косяк в pascal'e(и в Delphi)
:: Ваш ответ
Жирный  Курсив  Подчеркнутый  Перечеркнутый  {mpf5}  Код  Вставить ссылку 
:s1: :s2: :s3: :s4: :s5: :s6: :s7: :s8: :s9: :s10: :s11: :s12: :s13: :s14: :s15: :s16:


Максимальный размер аттача: 500KB.
Ваш логин: german1505 » Выход » ЛС
   Для печати Для печати