Форум: "Потрепаться";
Текущий архив: 2004.07.25;
Скачать: [xml.tar.bz2];
ВнизРавенство для 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;
Скачать: [xml.tar.bz2];
Память: 0.55 MB
Время: 0.04 c