Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2010.01.24;
Скачать: CL | DM;

Вниз

Delphi научился делить на 0   Найти похожие ветки 

 
Григорьев Антон ©   (2009-11-22 10:48) [0]

Берём такой код:

var
 I: Integer;
begin
 I := Round(8 / (4-4));
end;


Delphi по 2007-ую версию включительно этот код не компилирует, выдавая ошибку Constant expression violates subrange bounds. Но с 2009-ой версии эта ошибка переведена в разряд предупреждений, так что код компилируется и даже выполняется, I получает значение 0.

Офигеть "исправления" они там сделали...

P.S. Может, те билды D2009-2010, на которых проверялось, какие-то кривые? Попробуйте у себя, у кого есть эти версии.


 
AlexDan ©   (2009-11-22 11:17) [1]

Embarcadero® Delphi® 2010
да, действительно умеет, но в то же время
a:=2.6;
x:=int(2.6/a);
по прежнему 0, вот такие вот парадоксы.., как говориться исправляли бы уж всё..).


 
Григорьев Антон ©   (2009-11-22 11:38) [2]


> по прежнему 0, вот такие вот парадоксы..,

Переменная a какого типа?


 
AlexDan ©   (2009-11-22 11:59) [3]

real, это конечно немного не то, но из того же леса..


 
Григорьев Антон ©   (2009-11-22 12:19) [4]


> AlexDan ©   (22.11.09 11:59) [3]
> real

Ну так поменяйте на Extended, и будет вам счастье :)


 
Григорьев Антон ©   (2009-11-22 15:07) [5]

О проблеме сообщили в Quality Central, кто считает её важной, может проголосовать здесь: http://qc.embarcadero.com/wc/qcmain.aspx?d=79714


 
KilkennyCat ©   (2009-11-22 17:28) [6]

var
I, z: Integer;
begin
I := Round(8 / (z-z));

даст скомпилировать, но зато нормально вызовет ошибку при исполнении.
2010 сп2


 
KilkennyCat ©   (2009-11-22 17:28) [7]

да, пример с 4-4 работает отлично, то есть дает результат ноль.


 
Dimka Maslov ©   (2009-11-22 17:53) [8]

Результат деления на ноль зависит от состояния контрольного слова сопроцессора - либо результат получает значение "бесконечность" либо генерируется исключение. Функция же round получившая на входе неправильное вещественное число просто возвращает ноль. В ранних версиях delphi контрольное слово сопроцессора определяла режим генерирования исключения, а теперь, видимо, режим получения бесконечности. Учите мат. часть.


 
_oxffff_from_parents_home   (2009-11-22 18:52) [9]

Есть команда для очистки сопроцессора.


 
_oxffff_from_parents_home   (2009-11-22 18:52) [10]

Удалено модератором


 
Омлет ©   (2009-11-22 19:32) [11]

> а теперь, видимо, режим получения бесконечности

Это подлянка такая? :)


 
KilkennyCat ©   (2009-11-22 20:20) [12]


> Функция же round получившая на входе

причем здесь она? она что, первая выполняется?


 
Германн ©   (2009-11-22 20:32) [13]


> KilkennyCat ©   (22.11.09 20:20) [12]

Он просто сабж прочитал невнимательно :)


 
Dimka Maslov ©   (2009-11-22 21:30) [14]


> причем здесь она? она что, первая выполняется?


Функции Round, которая получает управление п о с л е д н е й, в качестве аргумента передаётся "неправильное" вещественное число, полученное в результате деления на ноль. И возвращает она ноль.


 
oxffff ©   (2009-11-22 22:29) [15]


> AlexDan ©   (22.11.09 11:17) [1]
> Embarcadero® Delphi® 2010
> да, действительно умеет, но в то же время
> a:=2.6;
> x:=int(2.6/a);
> по прежнему 0, вот такие вот парадоксы.., как говориться
> исправляли бы уж всё..).


Проблема отличная от той, о чем я подумал.
Вот то что по факту делается при  x:=int(2.6/a). Я вынес отдельную временную переменную которую неявно создает компилятор

var a:double;
   c:extended;
begin
a:=2.6;
c:=2.6/a;
c:=int(c);
showmessage(floattostr(c));

Однако результат 0

А так

var a:double;
begin
a:=2.6;
a:=2.6/a;
a:=int(a);
showmessage(floattostr(a));

результат  1.

Гм. интересненько.


 
KilkennyCat ©   (2009-11-22 22:46) [16]


> Dimka Maslov ©   (22.11.09 21:30) [14]

хорошо, а если не будет роунды?

А вообще, лично мне кажется несущественной ошибка. Ведь это ошибка на уровне компиляции, не относится к операционной системе, а компилятор в данном случае соптимизирует константы, а лично я такое выражение как (8/(4-4)) соптимизирую сам в момент написания, и значит, не допущу ошибки, а в случае использования переменных, как в моем примере, будет вопль системы.


 
oxffff ©   (2009-11-22 22:54) [17]


> KilkennyCat ©   (22.11.09 22:46) [16]


Есть предположение что проблема в int функции System.
Проверь.

var a:double;
   c:extended;
begin
a:=2.6;
c:=2.6/a;
showmessage(floattostr(c));
c:=int(c);
showmessage(floattostr(c));


 
oxffff ©   (2009-11-22 23:03) [18]

Решение проблемы.  
Они изменяют FPU Control Word в System.int

function myInt(const X: Extended): Extended;
asm
       FLD     X
       FWAIT
       FRNDINT
       FWAIT
end;

procedure TForm4.FormCreate(Sender: TObject);
var a:double;
begin
a:=2.6;
a:=myint(2.6/a);
showmessage(floattostr(a));
end;


 
Григорьев Антон ©   (2009-11-23 12:21) [19]


> oxffff ©   (22.11.09 22:54) [17]
> Есть предположение что проблема в int функции System.

Проблема не в функции int, а в особенностях вещественной арифметики. Число 2.6 не представляется в виде конечной двоичной дроби, поэтому любое его представление в двоичном виде есть округление. Extended оставляет 64 разряда, Double - 53 (или, может быть, чуть больше из-за нормализованной формы). А вычисления все делаются в Extended. Соответственно, константа 2.6 в Extended-представлении не совсем равна значению переменной a, которая имеет тип Double, и часть разрядов уже отброшена. Поэтому при делении получается не 1, а число, немного отличающееся от 1 (можно легко убедиться, что выражение 1-2.6/а примерно равно 3.42e-17). Отсюда и все проблемы. Число чуть меньше единицы, а Int работает строго в соответствии со своей спецификацией: не округляет, а просто отбрасывает дробную часть, оставляя 0.


 
Dimka Maslov ©   (2009-11-23 13:26) [20]


> хорошо, а если не будет роунды?


Получится число, обозначающее бесконечность. При преобразовании его к строке получается "+INF" или "-INF".



Страницы: 1 вся ветка

Текущий архив: 2010.01.24;
Скачать: CL | DM;

Наверх




Память: 0.51 MB
Время: 0.012 c
4-1217702866
kalexi
2008-08-02 22:47
2010.01.24
Как вызвать и обработать стандартный диалог открытия файлов?


2-1259747876
aza
2009-12-02 12:57
2010.01.24
Я правильно работаю с TIBSQL ?


2-1259848543
kate158
2009-12-03 16:55
2010.01.24
добавление д-х из excel на пересечении строки и столбца


2-1260107829
Natali
2009-12-06 16:57
2010.01.24
Delphi 7+SQL SERVER 2000+CORBA


2-1259755341
Andjey
2009-12-02 15:02
2010.01.24
Получение хэндла потока