Форум по Delphi программированию

Delphi Sources



Вернуться   Форум по Delphi программированию > Все о Delphi > Синтаксис
Ник
Пароль
Регистрация <<         Правила форума         >> FAQ Пользователи Календарь Поиск Сообщения за сегодня Все разделы прочитаны

Ответ
 
Опции темы Поиск в этой теме Опции просмотра
  #1  
Старый 09.04.2012, 16:07
hypertigr hypertigr вне форума
Прохожий
 
Регистрация: 17.03.2009
Сообщения: 2
Репутация: 10
Восклицание Floor: Delphi тоже ошибается!

Помогите пожалуйста досканально понять следующий факт
Код:
program Project1;
{$APPTYPE CONSOLE}
uses SysUtils, math;

procedure proc;
var a,b,c,d:double;
begin
  a:=0.1;
  b:=5;
  c:=floor(b/0.1);
  d:=floor(b/a);
  writeln(c);
  writeln(d);
end;

begin
  proc;
  readln;
end.

результат:
5.00000000000000E+0001
4.90000000000000E+0001

почему c=50, а d=49 ?

(компилятор turbo delphi 2006)
Заранее всем спасибо!
Ответить с цитированием
  #2  
Старый 09.04.2012, 16:32
Аватар для NumLock
NumLock NumLock вне форума
Let Me Show You
 
Регистрация: 30.04.2010
Адрес: Северодвинск
Сообщения: 5,426
Версия Delphi: 7, XE5
Репутация: 59586
Радость

все начинается с этого:
Код:
program Project1;

{$APPTYPE CONSOLE}

var
  a: Double;

begin
  a:=0.1;
  if 0.1=a then Writeln('Okay') else Writeln('Oops');
  Writeln(0.1-a);
  Readln;
end.

Цитата:
Oops
-5.54975987041018E-0018
__________________
Пишу программы за еду.
__________________
Ответить с цитированием
  #3  
Старый 09.04.2012, 17:26
hypertigr hypertigr вне форума
Прохожий
 
Регистрация: 17.03.2009
Сообщения: 2
Репутация: 10
По умолчанию

Я понимаю что сравивать два вещественных числа = "тыкать пальцем в небо". Ошибку свою понял но несовсем.
Как я понял делфи считает что 5/0,1<50
Интересно как она называется и охото узнать правила недопущения подобных ошибок, а также представление типа double в памяти.

Вот моя модификация
Код:
program Project2;
{$APPTYPE CONSOLE}
uses
  SysUtils,
  math;

function myFloor(x:double):integer;
begin
  if x>0 then result:=trunc(x)
         else result:=trunc(x)-1;
end;

procedure proc;
var a,b:double;
    c,d:integer;
begin
  a:=0.1;
  b:=5;
  c:=myFloor(b/0.1);
  d:=myFloor(b/a);
  writeln(c);
  writeln(d);
end;

begin
  proc;
  readln;
end.

результат
50
50

Застрахован ли такой подход от аналогичной ошибки при других значениях?
Ответить с цитированием
  #4  
Старый 10.04.2012, 08:56
Аватар для NumLock
NumLock NumLock вне форума
Let Me Show You
 
Регистрация: 30.04.2010
Адрес: Северодвинск
Сообщения: 5,426
Версия Delphi: 7, XE5
Репутация: 59586
Восклицание

для сравнения вещественных чисел есть функция в Math:
Код:
function CompareValue(const A, B: Extended; Epsilon: Extended): TValueRelationship;
function CompareValue(const A, B: Double; Epsilon: Double): TValueRelationship;
function CompareValue(const A, B: Single; Epsilon: Single): TValueRelationship;
ей передаются 2 сравниваемых вещественных числа и величина погрешности Epsilon.
__________________
Пишу программы за еду.
__________________
Ответить с цитированием
  #5  
Старый 10.04.2012, 22:51
AlexSku AlexSku вне форума
Специалист
 
Регистрация: 07.05.2007
Адрес: Москва
Сообщения: 884
Репутация: 21699
По умолчанию

Цитата:
Сообщение от hypertigr
Ошибку свою понял но несовсем.
Дробное число представляется точно, если оно степень двойки, напр., 4, 2, 1, 1/2. Другие числа (напр., 5, 50, 1/10) будут всегда округлены разрядной сеткой (длина мантиссы). Так что лучше для округления до целого использовать round, а не floor (хотя всё зависит от задачи).
Ответить с цитированием
Ответ


Delphi Sources

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения

BB-коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход


Часовой пояс GMT +3, время: 15:30.


 

Сайт

Форум

FAQ

RSS лента

Прочее

 

Copyright © Форум "Delphi Sources" by BrokenByte Software, 2004-2023

ВКонтакте   Facebook   Twitter