Форум: "Прочее";
Текущий архив: 2010.01.24;
Скачать: [xml.tar.bz2];
Вниз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;
Скачать: [xml.tar.bz2];
Память: 0.49 MB
Время: 0.005 c