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

Вниз

Равенство для real   Найти похожие ветки 

 
Sandman25 ©   (2004-07-06 12:48) [0]

В процессе обсуждения соседних веток мне пришла в голову глупая мысль.
А зачем вообще авторы Pascal/Delphi ввели операцию = для вещественных типов? Не правильнее ли было ее запретить?

И еще. Зачем нужно было поддерживать операции = и <> для логических операндов? Чтобы люди писали
if Cond = True и if Cond1 <> Cond2 вместо
if Cond и if Cond1 xor Cond2?


 
PVOzerski ©   (2004-07-06 12:51) [1]

IMHO Паскаль делался для обучения, а не для юзанья именно на Intel *86. Там даже не обсуждаются различия между числами с фиксированной и плавающей точкой (ср. в Си тип float, в Паскале - real). Так что формально сравнение на равенство никак не воспретишь, не ломая совершенно стандарт языка.


 
Григорьев Антон ©   (2004-07-06 12:56) [2]


> А зачем вообще авторы Pascal/Delphi ввели операцию = для
> вещественных типов?


С нулём сравнивать иногда бывает очень полезно. Да и ситуации всякие бывают.


> И еще. Зачем нужно было поддерживать операции = и <> для
> логических операндов? Чтобы люди писали
> if Cond = True и if Cond1 <> Cond2 вместо
> if Cond и if Cond1 xor Cond2?


Логический тип является в Паскале перечисляемым, т.е. записывается в виде (False,True). Из-за этого к нему применимы все операции сравнения, в т.ч. и "<" и ">" (при этом False<True). Если просто запретить такие операции, нарушится ортогональность языка, а ортогональный синтаксис легче запоминается. Кроме того, xor вместо <> - это очень неестественно. Я даже на плюсах пишу if (a!=0) вместо if (a) и т.д. - пускай оптимизатор сам разбирается.


 
GuAV ©   (2004-07-06 12:56) [3]


> Зачем нужно было поддерживать операции = и <> для логических
> операндов? Чтобы люди писали
> if Cond = True и if Cond1 <> Cond2 вместо
> if Cond и if Cond1 xor Cond2?

Имхо просто так получилось, что они определены для всех перечисленных.
Cond1 <> Cond2
А вот прикинь: оба LongBool, один LongBool(1), другой LongBool(-1). Учитывая, что LongBool юзается в WinAPI и может принимать и 1 и -1 ситуация реальная.


 
GuAV ©   (2004-07-06 12:58) [4]


> Логический тип является в Паскале перечисляемым, т.е. записывается
> в виде (False,True). Из-за этого к нему применимы все операции
> сравнения, в т.ч. и "<" и ">" (при этом False<True).


> Имхо просто так получилось, что они определены для всех
> перечисленных.

:)


 
Danilka ©   (2004-07-06 13:17) [5]

> А зачем вообще авторы Pascal/Delphi ввели операцию = для
> вещественных типов?

тогда и меньше/больше тоже надо запретить:

var R:Single;
begin
 R:=0.1;
 if R>0.1 then
  Label1.Caption:="Больше"
 else
  Label1.Caption:="Не больше"
end;

:))


 
GuAV ©   (2004-07-06 13:29) [6]

Я долго не мог понять почему не запретили
вызов конструкторов как процедур типа"Form1.Create;"  :)


 
Sandman25 ©   (2004-07-06 14:16) [7]

[1] PVOzerski ©   (06.07.04 12:51)

Логично. Наверное, именно в этом дело.

[2] Григорьев Антон ©   (06.07.04 12:56)

В то же время логический тип нельзя назвать всего лишь одним из перечисляемых типов. Ведь мы не можем написать
if otOne then даже если у нас есть TOrdinalType = (otOne, otTwo);

[3] GuAV ©   (06.07.04 12:56)

Это уже проблемы LongBool (и Widnows), а не паскаля ИМХО.

[5] Danilka ©   (06.07.04 13:17)

:)


 
jack128 ©   (2004-07-06 14:22) [8]


> Я долго не мог понять почему не запретили
> вызов конструкторов как процедур типа"Form1.Create;"  :)
а теперь понял? Проясни, пжлста. Если бы вызов Form1.Create(nil) не чем не отличался от вызова любого другого метода, я бы еше понял, а так, исключение в нем приводит к вызову деструктора. Нафиг это нужно было делать?  В общем я до сих пор этот момент не понял..


 
VMcL ©   (2004-07-06 14:22) [9]

>>Sandman25 ©   (06.07.04 12:48)

>Зачем нужно было поддерживать операции = и <> для логических операндов?

if (a = 0) = (b > 2) then ...

>А зачем вообще авторы Pascal/Delphi ввели операцию = для вещественных типов?

Вещественные числа не обязаны иметь дробную часть:
var
 a: Single;
begin
 a := 1;
 // ...
 if a = 1 then ...
end;


 
GuAV ©   (2004-07-06 14:23) [10]


> Это уже проблемы LongBool (и Widnows), а не паскаля ИМХО.

У носорога плохое зрение. Но при его весе это уже не его проблемы :)

Т.е. не LongBool (и Widnows)

по поводу  [3] - xor оказывается тоже "по умному" для этих. Т.е. проблемы нет. Отныне юзаю xor.


 
GuAV ©   (2004-07-06 14:25) [11]


> а теперь понял? Проясни, пжлста.

Имхо, для вызова из другого конструктора. Всего то.


 
jack128 ©   (2004-07-06 14:28) [12]


> Имхо, для вызова из другого конструктора. Всего то.
а зачем такие особенности с вот этим?

> исключение в нем приводит к вызову деструктора.


 
Sandman25 ©   (2004-07-06 14:29) [13]

[9] VMcL ©   (06.07.04 14:22)

>if (a = 0) = (b > 2) then ...

if not ((a = 0) xor (b > 2)) then

Тогда зачем xor? :)
Он эквивалентен <> для типов с всего 2 возможными значениями

>Вещественные числа не обязаны иметь дробную часть:

А вот это уже нужно проверять через приведение типов.
if Round(A) = 1.
Кстати, как насчет:
A := 1.1;
B := 2.1;
if Frac(A) = Frac(B) then
Можно ли заранее знать, выполнится ли if? Не влезая в дебри машинного представления...


 
GuAV ©   (2004-07-06 15:03) [14]


> > Имхо, для вызова из другого конструктора. Всего то.
> а зачем такие особенности с вот этим?
>
> > исключение в нем приводит к вызову деструктора.

Имхо так было удобнее реализовать. Все равно больше одно раза он вызван не будет.

type
TWhatever = class
public
  constructor Create;
  destructor Destroy; override;
end;

TSomething = class(TWhatever)
public
  constructor CreateSpecial;
end;

constructor TWhatever.Create;
begin
 try
   raise Exception.Create("realy bad thing");
 finally
   ShowMessage("finally - TWhatever.Create");
 end;
end;

constructor TSomething.CreateSpecial;
begin
 try
   Create;
 finally
   ShowMessage("finally - TSomething.CreateSpecial");
 end;
end;

destructor TWhatever.Destroy;
begin
 ShowMessage("TWhatever.Destroy");
 inherited;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
 TSomething.CreateSpecial;
end;


 
VMcL ©   (2004-07-06 15:19) [15]

>>Sandman25 ©   (06.07.04 14:29) [13]

>Тогда зачем xor? :)

Тогда зачем ты пишешь "Тогда зачем xor" вместо "D2EEE3E4E020E7E0F7E5EC20786F72"?


 
Sandman25 ©   (2004-07-06 15:22) [16]

[15] VMcL ©   (06.07.04 15:19)

Понятно. По историческим причинам.


 
jack128 ©   (2004-07-06 15:56) [17]


> Имхо так было удобнее реализовать. Все равно больше одно
> раза он вызван не будет.
его удобнее? Одну строчку вставить в асм код?

и пример у тебя не много не тот. При вызове констуктора внутри другого конструктора не происходит вызов _ClassCreate, а вот при вызове Form1.Create управление передается именно туда..

procedure       _ClassCreate;
asm
// код по созданию класса  
 ....

// уничтовение класса если есть подняли исключение
      JMP     _HandleAnyException

       {       destroy the object                                                      }

       MOV     EAX,[ESP+8+9*4]
       MOV     EAX,[EAX].TExcFrame.ConstructedObject
       TEST    EAX,EAX // не знаю, что это такое, но при вызове Form1.Create - этот тест проходится успешно..
       JE      @@skip
       MOV     ECX,[EAX]
       MOV     DL,$81
       PUSH    EAX
       CALL    dword ptr [ECX].vmtDestroy
       POP     EAX
       CALL    _ClassDestroy // уничтожаем объект
@@skip:
       {       reraise the exception   }
       CALL    _RaiseAgain
end;


 
GuAV ©   (2004-07-06 16:06) [18]


> и пример у тебя не много не тот.

When a constructor is called using an object reference (rather than a class reference), it does not create an object. Instead, the constructor operates on the specified object, executing only the statements in the constructor"s implementation, and then returns a reference to the object. A constructor is typically invoked on an object reference in conjunction with the reserved word inherited to execute an inherited constructor.
допиши inherited перед Create - будет тот.


 
VMcL ©   (2004-07-06 16:13) [19]

>>Sandman25 ©   (06.07.04 15:22) [16]

Я имел в виду (удобо)читаемость и понятность кода. Что легче понять:
if (a xor b) or ((y > x - c) xor d) then ...
или
if (a <> b) or ((y > x - c) <> d) then ...
?


 
Sandman25 ©   (2004-07-06 16:16) [20]

[19] VMcL ©   (06.07.04 16:13)

Это дело привычки ИМХО. xor гораздо проще какого-нибудь логарифма, но благодаря тому, что логарифмы учат еще в школе, проблем у начинающих с ними меньше, чем с xor.


 
Sandman25 ©   (2004-07-06 16:17) [21]

[19] VMcL ©   (06.07.04 16:13)

И, честно говоря, я ни разу не встречал в программах использование <> с логическими операндами :)


 
jack128 ©   (2004-07-06 16:25) [22]


> допиши inherited перед Create - будет тот.
да не будет нечего!!
Еще раз
constructor TSomething.CreateSpecial;
begin
try
  {inherited} Create; // в любом случае (есть inherited или нет) управление в _ClassCreate не перейдет
finally
  ShowMessage("finally - TSomething.CreateSpecial");
end;
end;

Ну пройдись отладчиком, если мне не веришь ;-)


 
Игорь Шевченко ©   (2004-07-06 16:36) [23]


> if Cond и if Cond1 xor Cond2?


Кто ж такой оператор на трезвую голову поймет-то ?


 
Sandman25 ©   (2004-07-06 16:39) [24]

[23] Игорь Шевченко ©   (06.07.04 16:36)

См. [20].
Кроме того, мне почему-то кажется, что Вы можете привести пример и гораздо более сложных выражений, которые упростить уже невозможно


 
Игорь Шевченко ©   (2004-07-06 16:42) [25]

Sandman25 ©   (06.07.04 16:39)


> Это дело привычки ИМХО


Это ж насколько надо так себя (и других, если, не дай Аллах, им такой код читать придется) не любить :)
Разумеется, писать так никто не запрещает, даже компилятор, но вот то, что такой код менее читабелен, чем первый вариант, я полагаю, видно невооруженным глазом :)


 
GuAV ©   (2004-07-06 16:45) [26]


> // в любом случае (есть inherited или нет) управление в
> _ClassCreate не перейдет

Может и не перейдет. Но все равно по сути это будет не вызов конструктора для class reference а для object reference. типа Form1.Create(AOwner);
ваще мы имхо чужую ветку флудим, спрои ка лучше в новой.


 
Sandman25 ©   (2004-07-06 16:47) [27]

[25] Игорь Шевченко ©   (06.07.04 16:42)

Наверное, я веду себя как упрямый баран, но я настаиваю, что это дело привычки :)
Пересечение множеств на паскале обозначили *, и никого это не путает, хотя и могло бы. Операцию <> обозначили словом xor, и это тоже никого не путает, просто большинство людей привыкли использовать именно <>.
Кстати, меня дико раздражает, что логические and, or и xor не обозначили как-нибудь вроде logand, logor и logxor. Как в фортране, AFAIR.


 
Игорь Шевченко ©   (2004-07-06 16:50) [28]

Sandman25 ©   (06.07.04 16:47)

> но я настаиваю, что это дело привычки


Так никто ж не спорит. Можно и операторы в одну строку писать - тоже дело привычки :) Лично мне, например, читать такой код было бы неудобно, так как для меня xor - это сложение по модулю 2.


> Пересечение множеств на паскале обозначили *


И это, вообще-то разумно :)


 
Sandman25 ©   (2004-07-06 16:57) [29]

[28] Игорь Шевченко ©   (06.07.04 16:50)

>так как для меня xor - это сложение по модулю 2.

А для меня это проверка на неравенство :) Во всяком случае, с таким подходом мне проще понять конструкцию 1001 xor 0111
Кстати, в десятичной системе
8 xor 5 = 3? Если да, то нужно будет переходить на Вашу позицию :)

>И это, вообще-то разумно :)

Depends. С геометрической интерпретацией, да. С алгебраической,
[1,2,3] * [2,4] = [2] выглядит как полный бред :)


 
DiamondShark ©   (2004-07-06 17:09) [30]


> Sandman25 ©   (06.07.04 16:17) [21]
> [19] VMcL ©   (06.07.04 16:13)
>
> И, честно говоря, я ни разу не встречал в программах использование
> <> с логическими операндами :)

Влёгкую.


procedure TMyClass.SetMyBoolProperty(Value: boolean);
begin
 if FMyBoolProperty <> Value then
   begin
     DoSomethingWithSideEffect();
     FMyBoolProperty := Value;
   end
end;


 
Sandman25 ©   (2004-07-06 17:11) [31]

[30] DiamondShark ©   (06.07.04 17:09)

Ну что тут возразишь :)


 
han_malign ©   (2004-07-06 17:49) [32]

<> vs. xor
- кстати, а мне и в голову до этого не приходило, что импликацию можно писать как <=, а аквивалентность как = - все not or, да not(xor) использовал...

>Пересечение множеств на паскале обозначили *...
>logand, logor и logxor
- ну, допустим, для коньюнкции и дизъюнкции в математике тоже специальные символы есть, вот только в ASCII их включить не озаботились - потому что на печатных машинках не было. А правила раскрытия скобок, для коньюнкции и дизъюнкции, объединения и пересечения - как раз соответсвуют сложению и умножению, так что выбор *, для множеств, вполне обоснован...


 
iZEN ©   (2004-07-06 19:31) [33]

/**Григорьев Антон ©   (06.07.04 12:56) [2]
> А зачем вообще авторы Pascal/Delphi ввели операцию = для
> вещественных типов?
С нулём сравнивать иногда бывает очень полезно. Да и ситуации всякие бывают.
*/
Ну уж с нулём Real всё равно не сравнишь - "не попадёшь".  В этом случае нужно в эпсилон попасть - тогда можно будет считать, что это "как бы нуль".
В Delphi есть определение NaN (not a number), в Java тоже есть.
А как дела обстоят с isNull?

Например, для Java:
Результат выражения Double.NaN == Double.NaN всегда равен false, поэтому приходится пользоваться методом класса-оболочки:
Float.isNaN(знаечение float) и Double.isNaN(знаечение double).

По поводу бесконечности в Java.
1f/0f = Float.POSITIVE_INFINITY
1d/0d = Double.POSITIVE_INFINITY
1f/-0f = Float.NEGATIVE_INFINITY
1d/-0d = Double.NEGATIVE_INFINITY


 
OSokin   (2004-07-06 21:18) [34]

SandMan, а зачем тогда они сделали строку, а не просто массив символов?


 
Sandman25 ©   (2004-07-07 09:25) [35]

[34] OSokin   (06.07.04 21:18)

>SandMan, а зачем тогда они сделали строку, а не просто массив символов?

Это потому что Pascal - строго типизированный ЯП. И дополнительно:
Если речь о String[n], то чтобы ускорить обработку за счет хранения длины.
Если речь о AnsiString, то чтобы не копировать когда не надо, и чтобы была совместимость с PChar.
Если речь об WideString, то чтобы была совместимость с PWideChar.



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

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

Наверх




Память: 0.57 MB
Время: 0.023 c
8-1078469704
AlexTregubov
2004-03-05 09:55
2004.07.25
Интерполяция изображения


3-1088584564
Ross
2004-06-30 12:36
2004.07.25
Транзакции


1-1089603759
Belocarsk
2004-07-12 07:42
2004.07.25
TreeView+картинки ,без ImageList


14-1089318984
urisan
2004-07-09 00:36
2004.07.25
проблемы с установкой delphi 8


3-1088659685
kalishenko
2004-07-01 09:28
2004.07.25
Pervasive 2000i &amp; DISTINCT