Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Прочее";
Текущий архив: 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
15-1258833857
oxffff
2009-11-21 23:04
2010.01.24
Drum bass. Красавец.


2-1260028195
dplz
2009-12-05 18:49
2010.01.24
Фон в listbox


2-1259680317
azl
2009-12-01 18:11
2010.01.24
Запись свойства компонента Visible в файл с помощью TFileStream


2-1259779619
Danco
2009-12-02 21:46
2010.01.24
Смена запуска Unit


1-1228253040
asail
2008-12-03 00:24
2010.01.24
Не рабтает смена лотка в QuickReport





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский