PDA

View Full Version : جابجایی دو متغییر بدون استفاده از متغییر کمکی



(امید)
سه شنبه 18 شهریور 1382, 07:52 صبح
سلام

خواستم به داغ شدن این تایک کمکی کرده باشم . چیزی تو ذهنم نبود . این موضوع رو که در فروم قدیمی هم آورده بودم دوباره اینجا می نویسم. بنابراین برای دوستان قدیمی نیست :wink:
چطور جای دو متغییر را بدون استفاده از متغییر سوم عوض کنیم?
جواب یک الگوریتم ساده ( و خوشگل) .

shaniaki
سه شنبه 18 شهریور 1382, 15:23 عصر
با عرض ادب:
این جور سوالات خیلی حال می ده این یکی از سوالاتیه که هر بار که برنامه نویسی جایی درس می دم می گم. اینم جواب:

a+b->a
a-b->b
a-b->a

حالا این رو بگید: بدون استفاده از if در «برنامه خودتان» برنامه ای بنویسید که از بین دو عدد کوچکتر و بزرگتر را پیدا کند.(تمام عملگر ها و توابع ریاضی در کامپایلر تعریف شده اند)

اگه از این ها دارید باز هم بگید :)

یه عشق برنامه نویسی خفن

Kambiz
سه شنبه 18 شهریور 1382, 23:05 عصر
برای جابجا کردن دو تا متغیر با هر اندازه و هر نوعی:

A <- A xor B
B <- A xor B
A <- A xor B

shaniaki جان بهتره موضوع جدید رو در تاپیک جدید عنوان کنیم.

houshmand
چهارشنبه 19 شهریور 1382, 13:38 عصر
حالا این رو بگید: بدون استفاده از if در «برنامه خودتان» برنامه ای بنویسید که از بین دو عدد کوچکتر و بزرگتر را پیدا کند.(تمام عملگر ها و توابع ریاضی در کامپایلر تعریف شده اند)


به وسیله GwBasic


10 INPUT "INPUT (a, b) ?",A,B
20 PRINT -((A>B)*A+(B>A)*B)

به وسیله Pascal


Program demo;
var
a,b :integer;
begin
readln(a,b);
writeln(ord(a>b)*a+ord(b>a)*b);
end.


:idea: در این برنامه از این خاصیت استفاده شده است که مقایسه A>B در پاسکال True یا Falseو در زبانهای Basicبرای درست مقدار 1- (منفی یک) و اشتباه 0 برمی گرداند :P

(امید)
چهارشنبه 19 شهریور 1382, 16:56 عصر
:تشویق: :تشویق:

جالب بود

اما قابل قبول نیست علیرضا جان.
اگر سورس تابع ord را برای مثال نگاه کنی نزدیک به 40 یا 50 تا IF چاق و چله می بینی :)

اگر از تابع بخوای استفاده کنی اونم نبایئ IF داشته باشه.
( البته اونطوری که مد نظر دوستمون بود :wink: )

v_shalchian
چهارشنبه 19 شهریور 1382, 19:14 عصر
سلام
این هم جوابش :

max=((a + b) + abs(a - b)) / 2
min=((a + b) - abs(a - b)) / 2
البته منظور از abs قدر مطلق است.

houshmand
چهارشنبه 19 شهریور 1382, 21:26 عصر
max=((a + b) + abs(a - b)) / 2
min=((a + b) - abs(a - b)) / 2
البته منظور از abs قدر مطلق است.
دوست عزیز اصلاٌ قبول نیست :mrgreen:
چون توی زبانهای برنامه نویسی فکر کنم برای تابع قدر مطلق از if استفاده می کند و بنا به گفته آقا امید قبول نیست :!:
:idea: باید برای قدر مطلق کردن بدون IF یک راه بگی :mrgreen:

houshmand
چهارشنبه 19 شهریور 1382, 21:29 عصر
اگر سورس تابع ord را برای مثال نگاه کنی نزدیک به 40 یا 50 تا IF چاق و چله می بینی :)

اگر از تابع بخوای استفاده کنی اونم نبایئ IF داشته باشه.

دوست عزیز
در مورد Ord من بورلند پاسکال الان ندارم که ببینم تابع Ord داخل یونیتSystem از If
استفاده کرده یا نه
ولی تا جایی که یادم می یاد این یونیت با زبان ماشین نوشته شده و زبان ماشین If ندارد! :lol:
:!: توی یونیتSystem دلفی هم تعریف این تابع را ندیدم
ولی در ابتدای آن نوشته:


unit System; { Predefined constants, types, procedures, }
{ and functions (such as True, Integer, or }
{ Writeln) do not have actual declarations.}
{ Instead they are built into the compiler }
{ and are treated as if they were declared }
{ at the beginning of the System unit. }


که فکر کنم تابع ord جزء این هااست! :mrgreen:
ولی باشه این هم یک راه دیگه
اگه باز هم IF داشت بگو


Program demo;
var
a,b :integer;
begin
readln(a,b);
writeln(integer(a>b)*a+integer(b>a)*b);
end.

Kambiz
چهارشنبه 19 شهریور 1382, 21:49 عصر
برای پایان دادن به این اختلاف نظرها صورت مسئله‌‌ رو به این صورت در نظر بگیرید:

از بین دو عدد A و B کوچکترین و بزرگترین عدد را بدون استفاده از هرگونه مقایسه ضمنی یا عینی تعیین کنید.

Kambiz
چهارشنبه 19 شهریور 1382, 21:53 عصر
... این یونیت با زبان ماشین نوشته شده و زبان ماشین If ندارد! ...


ماشینهایی محاسبی که در گروه کامپیوترها قرار می‌گیرند حداقل یک دستور انشعاب شرطی دارند.

v_shalchian
پنج شنبه 20 شهریور 1382, 00:28 صبح
دوست عزیز اصلاٌ قبول نیست :mrgreen:
چون توی زبانهای برنامه نویسی فکر کنم برای تابع قدر مطلق از if استفاده می کند و بنا به گفته آقا امید قبول نیست :!:
:idea: باید برای قدر مطلق کردن بدون IF یک راه بگی :mrgreen:
اینم یه روش ابداعی خودم برای محاسبه قدر مطلق بدون if:

abs=(2*floor(atan(atan(atan(x))))+1)*x
منظور از floor جزء صحیح و منظور از atan آرکتانژانت است.

houshmand
پنج شنبه 20 شهریور 1382, 01:17 صبح
abs=(2*floor(atan(atan(atan(x))))+1)*x
منظور از floor جزء صحیح و منظور از atan آرکتانژانت است.
دوست عزیز این دیگه بد تر شد که ! :wink:

v_shalchian
پنج شنبه 20 شهریور 1382, 09:30 صبح
دوست عزیز این دیگه اصلا هم بدتر نشد چون کاملا درسته و هیچ دستور if هم به کار نرفته



abs=(2*floor(0.5*(atan(x)))+1)*x

houshmand
پنج شنبه 20 شهریور 1382, 11:25 صبح
دوست عزیز این دیگه اصلا هم بدتر نشد چون کاملا درسته و هیچ دستور if هم به کار نرفته



abs=(2*floor(atan(0.5*(atan(x))))+1)*x
خوب دوست عزیز تابع arctan و جزء صحیح بنویس که داخلش if نباشه :oops:
چون توی زبانهای برنامه نویسی برای نوشتن این توابع فکر کنم از if استفاده می کنند :oops:
و بنا به گفته آقا امید ...

houshmand
پنج شنبه 20 شهریور 1382, 13:59 عصر
ماشینهایی محاسبی که در گروه کامپیوترها قرار می‌گیرند حداقل یک دستور انشعاب شرطی دارند.
من زبان ماشین بلد نیستم ولی به بخش
<span dir=ltr>80x86 Instructions</span>
از کتاب
<span dir=ltr>
the 80x86 IBM PC
and Compatible
Computers
(Volume I)
Assembly Language
Programing on the IBM PC,
PS,and Compatibles

Muhammad Ali Mazidi
Janice Gillispie Mazidi</span>
نگاه کردم ولی if ندیدم!
و پاسکال هم Compatible 80x86

houshmand
پنج شنبه 20 شهریور 1382, 14:05 عصر
از بین دو عدد A و B کوچکترین و بزرگترین عدد را بدون استفاده از هرگونه مقایسه ضمنی یا عینی تعیین کنید.

این هم یک روش :
البته برای زمانی که دادهها از نوع Longint باشد :lol: (و بدون متغییر کمکی :lol: :lol: :lol: )


program minmaxd2;
&#123;$APPTYPE CONSOLE&#125;
uses
SysUtils;
var
a,b&#58;longint;
begin
readln&#40;a,b&#41;;
writeln&#40;'max=',&#40;2*a-&#40;&#40;a-b&#41; shr 31&#41;*2*&#40;a-b&#41;&#41; shr 1&#41;;
writeln&#40;'min=',&#40;2*b+&#40;&#40;a-b&#41; shr 31&#41;*2*&#40;a-b&#41;&#41; shr 1&#41;;
readln;
end.

اگر به این برنامه خوب دقت کنید از روش جناب v_shalchian استفاده شده + یک کم تغییرات برای abs

//***************************
:!: البته دوست دارم دیگر دوستان در این باره نظر بدهند
و راه حل های دیگری ارائه بدهند
و هیچ کس از اینکه درباره جوابش نظر بدهیم ناراحت نشود

موفق باشید

(امید)
پنج شنبه 20 شهریور 1382, 17:46 عصر
:تشویق: :تشویق: :تشویق:

احسنت به این برنامه نویسهای خوب(علیرضا و v_shalchian و لاغیر ... ) 8)

علیرضا جان تابع ord رو می تونی سورسش رو تو خود دلفی ببینی.

writeln(integer(a>b)*a+integer(b>a)*b);
راه حل خیلی قشنگیه ولی تابع integer هم IF داره ( بالای 30 تا :) )

برای راه حل آخری هر کار کردم IF ی پیدا نکردم :D .
حالا باید دید آقای شنیکی چه الگوریتمی رو در نظر دارن.

:)

Kambiz
پنج شنبه 20 شهریور 1382, 19:07 عصر
ماشینهایی محاسبی که در گروه کامپیوترها قرار می‌گیرند حداقل یک دستور انشعاب شرطی دارند.
من زبان ماشین بلد نیستم ولی به بخش
<span dir=ltr>80x86 Instructions</span>
از کتاب
<span dir=ltr>
the 80x86 IBM PC
and Compatible
Computers
(Volume I)
Assembly Language
Programing on the IBM PC,
PS,and Compatibles

Muhammad Ali Mazidi
Janice Gillispie Mazidi</span>
نگاه کردم ولی if ندیدم!
و پاسکال هم Compatible 80x86

مسلما در یک زبان ماشین نمی‌توانید دستورات زبانهای سطح بالا یا متوسط را به همان شکل ببینید. در اکثر موارد یک دستور از زبانهای سطح بالا به چندین دستور ماشین ترجمه می‌شوند اما بطور استثنا دستورالعمل اگر٬ مترادف خود به عنوان پرش شرطی را در زبان ماشین دارد.

shaniaki
پنج شنبه 20 شهریور 1382, 19:09 عصر
با عرض ادب:

الگوریتم جالبی است فقط تنها مورد آن همان طور که اشاره کردید خاص بودن آن برای یک نوع داده است که با کمی تغییر به دیگر داده ها نیز قابل تعمیم است.
به طور کلی چون اساس شرط گیت های منطقی است فکر نمی کنم از راه محاسباتی صرف یک راه حل کلی برای تمامی حالات(هر ماشینی و هر زبانی) بتوان داد اما یک راه آن همانطور که اشاره شد تقریب تابع با استفاده از توابع و محاسبات ریاضی ابتدایی است. راهی که گفته ششدتقریب با استفاده از atan بود که فکر جالبی بود با استفاده از بسط ها(تیلور و ...) هم می توان به آن نزدیک شد.
البته من چون به این جا ها رسیده بودم سعی کردم سوال را طوری مطرح کنم که همان جواب اول( با abs) منظور نظر باشد ولی حالا که به این جا رسیده ایم اگر کسی راه حل بهتری سراغ دارد بگوید ما که تا همین جا متوقف شدیم.

یه عشق برنامه نویسی خفن.

Mashatan
پنج شنبه 20 شهریور 1382, 23:18 عصر
در زبان اسمبلی برای درست کردن یک شرط از دو دستور Cmp و Jump استفاده میشه و برای فهمیدن آن شما یک تیکه برنامه بنویسید مثل زیر :


procedure TForm1.FormCreate&#40;Sender&#58; TObject&#41;;
var
a,b&#58;Integer;
begin
a&#58;=1;
b&#58;=1;
if a=b then begin
beep;
end;
end;

و بعد روی خطی که if قرار دارد Berakpoint بگذارید و برنامه را اجرا کنید و وقتی برنامه روی Breakpoint ایستاد به منوی View\Debug Winodws بروید و CPU رو انتخاب کنید و اونجا میتونید همزمان هم Assembly و هم زبان ماشین هر دستور Delphi رو ببینید !
و حتی دستوراتی که شما سورس شو ندارید (مثل Kernel Windows )رو به زبان ماشین و اسمبلی ببینید !


BA 01 00 00 00 mov edx,$00000001
3B D0 cmp edx,dax
7505 jnz &#40;+$05&#41;
E8 25 F1 Fb FF call Beep
C3 ret

و اگر شما از F8 استفاده کنید Step Over جلو میره (داخل Call نمیشود)
و اگر از F7 استفاده کنید Trace into جلو میره و داخل Call هم میره!

SyntaxCheck
شنبه 22 شهریور 1382, 04:46 صبح
سلام دوستان
برای اجرای این کد یک Button و دو Editbox روی فرمتون قرار بدید. داخل ادیت باکسها اعدادی رو که قصد مقایسه داریر رو بنویسید.تابع ماکزیمم دو عدد رو برمیگردونه بدون کنترل شرطی.اگر خطی رو که جلوش // هست رو هم به برنامه برگردونید، مقدار مینیمم دو عدد برگشت داده میشه.



procedure TForm1.Button1Click&#40;Sender&#58; TObject&#41;;
var
buf&#58; array&#91;0..1&#93;of integer;
i,a,b&#58; Word;
begin
a &#58;= StrToInt&#40;Edit1.Text&#41;;
b &#58;= StrToInt&#40;Edit2.Text&#41;;
buf&#91;0&#93; &#58;= StrToInt&#40;Edit1.Text&#41;;
buf&#91;1&#93; &#58;= StrToInt&#40;Edit2.Text&#41;;
asm
push ax
push bx
push cx
push dx
xor a,$8000
xor b,$8000
mov ax,a
xor ax,b
mov dx,0
mov cx,16
clc
@aa&#58;
mov bx,0
shl ax,1
jc @carry_sets
inc dl
loop @aa
@carry_sets&#58;
inc dl
mov cl,16
sub cl,dl
mov ax,a
xor ax,b
mov bx,a
shr bx,cl
shr ax,cl
and ax,1
and bx,1
xor bx,ax
// xor bx,1
mov i,bx
pop dx
pop cx
pop bx
pop ax
end;
Caption &#58;= IntToStr&#40;buf&#91;i&#93;&#41;;
end;

اگر قصد تغییر کد رو دارید، به هیچ وجه Push و Pop ها رو از کد برندارید.
ای بابا. این همه زور زدم اینو نوشتم آخر سر بنام مهمان پست شد. :cry: :wink:

Kambiz
شنبه 22 شهریور 1382, 05:59 صبح
سلام دوستان
برای اجرای این کد یک Button و دو Editbox روی فرمتون قرار بدید. داخل ادیت باکسها اعدادی رو که قصد مقایسه داریر رو بنویسید.تابع ماکزیمم دو عدد رو برمیگردونه بدون کنترل شرطی.اگر خطی رو که جلوش // هست رو هم به برنامه برگردونید، مقدار مینیمم دو عدد برگشت داده میشه.



procedure TForm1.Button1Click&#40;Sender&#58; TObject&#41;;
var
buf&#58; array&#91;0..1&#93;of integer;
i,a,b&#58; Word;
begin
a &#58;= StrToInt&#40;Edit1.Text&#41;;
b &#58;= StrToInt&#40;Edit2.Text&#41;;
buf&#91;0&#93; &#58;= StrToInt&#40;Edit1.Text&#41;;
buf&#91;1&#93; &#58;= StrToInt&#40;Edit2.Text&#41;;
asm
push ax
push bx
push cx
push dx
xor a,$8000
xor b,$8000
mov ax,a
xor ax,b
mov dx,0
mov cx,16
clc
@aa&#58;
mov bx,0
shl ax,1
jc @carry_sets
inc dl
loop @aa
@carry_sets&#58;
inc dl
mov cl,16
sub cl,dl
mov ax,a
xor ax,b
mov bx,a
shr bx,cl
shr ax,cl
and ax,1
and bx,1
xor bx,ax
// xor bx,1
mov i,bx
pop dx
pop cx
pop bx
pop ax
end;
Caption &#58;= IntToStr&#40;buf&#91;i&#93;&#41;;
end;

اگر قصد تغییر کد رو دارید، به هیچ وجه Push و Pop ها رو از کد برندارید.
ای بابا. این همه زور زدم اینو نوشتم آخر سر بنام مهمان پست شد. :cry: :wink:

یک دونه اگر تو کدی که نوشتی وجود داره: jc @carry_sets که معادل کد زیر هست:


c&#58; boolean;

if c then goto carry_set;
اگر قراره دستورات شرطی ماشین رو شرط حساب نکنید پس این کد زیر هم باید جواب باشه٬ که البته نیست.


function Min&#40;A, B&#58; Integer&#41;&#58; Integer;
asm
mov eax, A
cmp eax, B
jl @finish
mov eax, B
@finish&#58;
end;

function Max&#40;A, B&#58; Integer&#41;&#58; Integer;
asm
mov eax, A
cmp eax, B
ja @finish
mov eax, B
@finish&#58;
end;

shaniaki
شنبه 22 شهریور 1382, 09:54 صبح
با عرض ادب:
حق با جناب DelphiArea است.
همانطور که گفتم اساس دستورات شرطی که در برنامه نویسی استفاده می کنیم گیت های منطقی پردازنده است و دستوراتی مانند xor و cmp همگی از این دسته اند.

یه عشق برنامه نویسی خفن

SyntaxCheck
شنبه 22 شهریور 1382, 15:24 عصر
خوب خوشحالم که بحث و صحبت به اینجا رسید. دوستان بنده یه توضیح کوچولو راجع به دستورات مقایسه ای و انشعابی میدم. دسته اول JZ,JNZ,JO,JNO,JS,JNS,JC,JNC,JP,JNP و در نهایت دسته دوم با یک عضو JMP همگی جزو گروه دستورات خانواده انشعابها (Branches)هستند. JMP انشعاب قطعی(Unconditional Branch) هست و سری اول دستورات که ذکر کردم جزو انشعابات غیر قطعی.البته شرطی خواندن این دستورات انشعابی اصلا کار صحیحی نیست و اینها صرفا پرشهای انشعابی قطعی و یا غیر قطعی هستند. اما دستور شرطی به تنهایی در اسمبلی معنی نداره و به یک بلوک دستور ،ممکنه که شرط گفته بشه، زمانی که یک دستور مقایسه ای و یک دستور انشعابی همراه هم باشند. در زیر چند حالت ممکن رو برای روشن تر شدن منظورم ذکر میکنم:
1) در ابتدای بلوک CMP انجام شود و سپس از دسته انشعابی اول برای جهش استفاده شود این حالت همون IF در زبانهای سطح بالاست.(که طبق راهی که دوست عزیز آقای مشاطان عرض کردند میتونید الگوریتم IF رو مشاهده کنید که یک دستور نیست و مجموعه ای از دو دستور CMP و یک دستور انشعابی هست)
2) در ابتدای بلوک CMP انجام شود و از هیچ دستور انشعابی در ادامه استفاده نشود.این حالت مقایسه محض نام دارد و صرفا جهت تنظیم فلاگها برای مصارف بعدی کاربرد دارد.
3) در بلوک صرفا از دستورات انشعابی(Branches) استفاده شود و در هیچ جای بلوک CMP انجام نشود. این حالت مانند انجام یک پرش از یک قسمت برنامه به یک قسمت دیگر برنامه ممکن است باشد.

اما بنده هم به خوبی میدونم که با یک CMP و یک بلوک کوچیک میشه عدد Max و Min و بدست آورد اما وقتی مسئله مطرح شده توی این تاپیک رو دیدم این الگوریتم رو روش کار کردم که از فرض مسئله تبعیت بکنه.اما آقا کامبیز اگر مثال شما رو (if c then goto carry_set) نگاه کنیم به وضوح از IF در اون استفاده شده و الگوریتم پروسه ای که من نوشتم اصلا همچین کاری رو نمیکنه و یا مثال حضرتعالی با CMP.
اما دوست عزیز آقای Shaniaki ، اساس بله اما خود دستور شرط نه.
اما مسئله اصلی که گویا اصلا بهش توجهی نشده الگوریتم بکار رفته در این پروسه هست. من گفتم الان رفقا اینو که ببینن کلی راجع بهش صحبت میشه. اگر دو عدد رو به مبنای دو ببریم و اون دوتا رو با هم XOR کنیم آخرین بیت روشن جواب بیتی از دو عدد خواهد بود که معین کننده عدد Max و یا Min هست. بزارید با یه مثال بگم:

01010111=87 عدد 0 ام
01100101=101 عدد 1 ام
_____________XOR
00110010=50

بیت سوم از سمت راست همون بیتی از 87و101 هست که اگر XOR همین بیت (1) با همین بیت از عدد اول یعنی (0) انجام بشه عدد 1 بدست میاد که این امر نشون دهنده اونه که مقدار MAX همون عدد 1 ام هست. حالا عملیاتی در ابتدا برای تصحیح بیت علامت انجام شده که برای اعداد اینتیجر همون XOR کردن با $8000 هست و یا برای برگشت مینیمم که XOR کردن جواب با 1 هست(خط //).

Kambiz
شنبه 22 شهریور 1382, 16:13 عصر
خوب خوشحالم که بحث و صحبت به اینجا رسید. دوستان بنده یه توضیح کوچولو راجع به دستورات مقایسه ای و انشعابی میدم. دسته اول JZ,JNZ,JO,JNO,JS,JNS,JC,JNC,JP,JNP و در نهایت دسته دوم با یک عضو JMP همگی جزو گروه دستورات خانواده انشعابها (Branches)هستند. JMP انشعاب قطعی(Unconditional Branch) هست و سری اول دستورات که ذکر کردم جزو انشعابات غیر قطعی.البته شرطی خواندن این دستورات انشعابی اصلا کار صحیحی نیست و اینها صرفا پرشهای انشعابی قطعی و یا غیر قطعی هستند. اما دستور شرطی به تنهایی در اسمبلی معنی نداره و به یک بلوک دستور ،ممکنه که شرط گفته بشه، زمانی که یک دستور مقایسه ای و یک دستور انشعابی همراه هم باشند. در زیر چند حالت ممکن رو برای روشن تر شدن منظورم ذکر میکنم:
1) در ابتدای بلوک CMP انجام شود و سپس از دسته انشعابی اول برای جهش استفاده شود این حالت همون IF در زبانهای سطح بالاست.(که طبق راهی که دوست عزیز آقای مشاطان عرض کردند میتونید الگوریتم IF رو مشاهده کنید که یک دستور نیست و مجموعه ای از دو دستور CMP و یک دستور انشعابی هست)
2) در ابتدای بلوک CMP انجام شود و از هیچ دستور انشعابی در ادامه استفاده نشود.این حالت مقایسه محض نام دارد و صرفا جهت تنظیم فلاگها برای مصارف بعدی کاربرد دارد.
3) در بلوک صرفا از دستورات انشعابی(Branches) استفاده شود و در هیچ جای بلوک CMP انجام نشود. این حالت مانند انجام یک پرش از یک قسمت برنامه به یک قسمت دیگر برنامه ممکن است باشد.

اما بنده هم به خوبی میدونم که با یک CMP و یک بلوک کوچیک میشه عدد Max و Min و بدست آورد اما وقتی مسئله مطرح شده توی این تاپیک رو دیدم این الگوریتم رو روش کار کردم که از فرض مسئله تبعیت بکنه.اما آقا کامبیز اگر مثال شما رو (if c then goto carry_set) نگاه کنیم به وضوح از IF در اون استفاده شده و الگوریتم پروسه ای که من نوشتم اصلا همچین کاری رو نمیکنه و یا مثال حضرتعالی با CMP.
اما دوست عزیز آقای Shaniaki ، اساس بله اما خود دستور شرط نه.
اما مسئله اصلی که گویا اصلا بهش توجهی نشده الگوریتم بکار رفته در این پروسه هست. من گفتم الان رفقا اینو که ببینن کلی راجع بهش صحبت میشه. اگر دو عدد رو به مبنای دو ببریم و اون دوتا رو با هم XOR کنیم آخرین بیت روشن جواب بیتی از دو عدد خواهد بود که معین کننده عدد Max و یا Min هست. بزارید با یه مثال بگم:

01010111=87 عدد 0 ام
01100101=101 عدد 1 ام
_____________XOR
00110010=50

بیت سوم از سمت راست همون بیتی از 87و101 هست که اگر XOR همین بیت (1) با همین بیت از عدد اول یعنی (0) انجام بشه عدد 1 بدست میاد که این امر نشون دهنده اونه که مقدار MAX همون عدد 1 ام هست. حالا عملیاتی در ابتدا برای تصحیح بیت علامت انجام شده که برای اعداد اینتیجر همون XOR کردن با $8000 هست و یا برای برگشت مینیمم که XOR کردن جواب با 1 هست(خط //).

ممنون از توضیحات.

منم در توضیح کد خودم اینو بگم که به جای دستور CMP میشه از دستور SUB هم استفاده کرد. تنها فرق ماهیتی که این دو دستور با هم دارند اینه که CMP رجیستر اول رو تغییر نمیده ولی SUB تغییر میده. یعنی کدی رو که در بالا نوشتم رو میشه بدون استفاده از CMP بصورت زیر هم نوشت:


function Min&#40;A, B&#58; Integer&#41;&#58; Integer;
asm
mov eax, A &#123; eax &lt;- A &#125;
sub eax, B &#123; eax &lt;- eax - B &#125;
jl @finish &#123; if eax &lt; 0 goto finish &#125;
xor eax, eax &#123; eax &lt;- 0 &#125;
@finish&#58;
add eax, B &#123; eax &lt;- eax + B &#125;
end;

function Max&#40;A, B&#58; Integer&#41;&#58; Integer;
asm
mov eax, A &#123; eax &lt;- A &#125;
sub eax, B &#123; eax &lt;- eax - B &#125;
ja @finish &#123; if eax > 0 goto finish &#125;
xor eax, eax &#123; eax &lt;- 0 &#125;
@finish&#58;
add eax, B &#123; eax &lt;- eax + B &#125;
end;

SyntaxCheck
شنبه 22 شهریور 1382, 16:31 عصر
سلام
صحبت شما کاملا صحیحه اما به یک نکته توجه کنید من انواع انشعابهای مطلق و غیر مطلق رو نام بردم اما شما از یک دستور پرش شرطی استفاده کردید (JL). پرشهای شرطی (comparison) عبارتند از:

JE,JNE,JL,JNGE,JLE,JNG,JG,JNLE,JGE,JNL,JB,JNAE,JBE ,JNA,JA,JNBE,JAE,JNB

فراموش نشه که اینها پرشهای شرطی هستند و قبلیها که عرض کردم انشعابهای مطلق و غیر مطلق.
به هر حال کارهای زیادی میشه انجام داد.البته قصد من نوشتن کد بهینه نبود و فقط قصدم از مثال و پروسه ای که خودم نوشتم نشون دادن الگوریتمش بود اگر روی این الگوریتم کار بشه ممکنه چیزهای خیلی بهینه تری ازش بیرون بیاد.

پیروز باشید
________________
راستی آقا کامبیز من یه تشکر بابت یونیت تاریخ بشما بدهکارم.ممنون :wink:

Kambiz
شنبه 22 شهریور 1382, 16:57 عصر
سلام
صحبت شما کاملا صحیحه اما به یک نکته توجه کنید من انواع انشعابهای مطلق و غیر مطلق رو نام بردم اما شما از یک دستور پرش شرطی استفاده کردید (JL). پرشهای شرطی (comparison) عبارتند از:

JE,JNE,JL,JNGE,JLE,JNG,JG,JNLE,JGE,JNL,JB,JNAE,JBE ,JNA,JA,JNBE,JAE,JNB

فراموش نشه که اینها پرشهای شرطی هستند و قبلیها که عرض کردم انشعابهای مطلق و غیر مطلق.
به هر حال کارهای زیادی میشه انجام داد.البته قصد من نوشتن کد بهینه نبود و فقط قصدم از مثال و پروسه ای که خودم نوشتم نشون دادن الگوریتمش بود اگر روی این الگوریتم کار بشه ممکنه چیزهای خیلی بهینه تری ازش بیرون بیاد.

پیروز باشید
________________
راستی آقا کامبیز من یه تشکر بابت یونیت تاریخ بشما بدهکارم.ممنون :wink:

خوشحالم که از یونیت تاریخ استفاده می‌‌کنید٬ قابل شما رو نداره.

من صحبتم اصلا" سر این نیست که کدوم کد بهینه تره. اصلا سوال راجب این مورد نیست. من سعی دارم این رو بگم که هر گونه انشعابی در کد حاصل به معنای اینه که جواب صورت مسئله داده نشده. وگرنه فرقی بین انشعاب بر اساس Carry Flag و Sign Flag وجود نداره و هر دو بر اساس یک بیت تصمیم می‌گیرند که انشعاب رو انجام بدهند یا دستورالعمل بعدی رو.

من که از همون اول گفتم که کد من جواب مسئله نیست و البته کد شما هم نمی‌تونه جواب باشه. کد ماشینی می‌تونه جواب باشه که هیچ انشعابی درش وجود نداشته باشه و دستورات بصورت متوالی انجام بشوند (یا در زبان الگوریتمی: فقط از ساختار توالی و بدون استفاده از ساختارهای تکرار و شرط به جواب برسیم).

امیدوارم توانسته باشم رفع سؤتفاهم کنم.

SyntaxCheck
شنبه 22 شهریور 1382, 17:42 عصر
سلام
در انشعابها هیچ شرطی کنترل نمیشه و این مسئله درکش کمی مشکله.ما چون میبینیم مثلا در JC زمانی که Carry Flag ست میشه کنترل به آفست دیگه ای منتقل میشه تصور شرط برامون بوجود میاد. این مسئله در حقیقت شرط. درک عملی تفاوت Branch ها و comparison ها و اینکه چرا اینها شرطی هسنت و اونها نیستن مشکله. اما واقعیت اینه که Branch ها نیستند.

Kambiz
شنبه 22 شهریور 1382, 18:03 عصر
سلام
در انشعابها هیچ شرطی کنترل نمیشه و این مسئله درکش کمی مشکله.ما چون میبینیم مثلا در JC زمانی که Carry Flag ست میشه کنترل به آفست دیگه ای منتقل میشه تصور شرط برامون بوجود میاد. این مسئله در حقیقت شرط. درک عملی تفاوت Branch ها و comparison ها و اینکه چرا اینها شرطی هسنت و اونها نیستن مشکله. اما واقعیت اینه که Branch ها نیستند.
:shock: :!: :?:

ما یک مقایسه رو به غیر از تغییر مسیر اجرای برنامه برای چه کاری انجام می‌دهیم؟
حتی در کد زیر:


B&#58; Boolean;

B &#58;= X > Y;
هم انشعاب وجود داره.

Mashatan
شنبه 22 شهریور 1382, 23:18 عصر
در اسمبلی به تمام دستوارت JE,JNE,JL,JNGE,JLE,JNGو ... Jump گفته میشه
ما در اسمبلی دو جور Jump داریم Near و ّFar و همانطوری که میدونید Jump دستوری که غیر
مستقیم میتونه رجیستر EIP را عوض کند برای همین دستور بسیار کلیدی هست

به Jump های که به جای Address از عدد نسبی استفاده میکنند Near گفته میشه
به Jump های که مستقیم از Address استفاده میکنند Far گفته مبشه

houshmand
یک شنبه 23 شهریور 1382, 23:48 عصر
علیرضا جان تابع ord رو می تونی سورسش رو تو خود دلفی ببینی.
راه حل خیلی قشنگیه ولی تابع integer هم IF داره ( بالای 30 تا :) )

:?: می شود بگویید داخل چه فایلی است؟ :cry:
//************************************
به پاسکال زبان کنترل دقیق دادهها لقب داده اند و مانند زبانهای نسل Basic نمی توان یک متغییر Boolean را به یک Integer نسبت داد
که من برای قالب ریزی یک Boolean بهInteger از توابع Ord یاIntegerاستفاده کردم
/*******************
ولی خوب برای این کار به صورت دستی!





program minmax123;

&#123;$APPTYPE CONSOLE&#125;

uses
SysUtils;

var
a,b &#58;integer;
ab,ba&#58;^byte;
Bolab,bolba&#58;boolean;
begin
readln&#40;a,b&#41;;
bolab&#58;=a>b;
bolba&#58;=b>a;
ab&#58;=@bolab;
ba&#58;=@bolba;
writeln&#40;ab^*a+ba^*b&#41;;
readln;
end.



ولی اگر



حتی در کد زیر:


B&#58; Boolean;

B &#58;= X > Y;
هم انشعاب وجود داره.
با این روش: :lol:


Program minmax2;

&#123;$APPTYPE CONSOLE&#125;

uses
SysUtils;

var
a,b,c,t &#58;integer;

d&#58;^byte;
begin
readln&#40;a,b&#41;;
d&#58;=@c;

c&#58;=b-a ;
d^&#58;=d^ shr 7;
t&#58;=d^*a;

c&#58;=a-b ;
d^&#58;=d^ shr 7;

t&#58;=t+d^*b;
writeln&#40;t&#41;;
readln;
end.

موفق باشید

SyntaxCheck
دوشنبه 24 شهریور 1382, 02:27 صبح
دوست عزیزم آقا کامبیز دلیل استفاده از CMP بستگی به برنامه نویس داره. معمول اون پرش کردن در ادامه بلوک هست اما نه مطلق در جواب قبلیم این نوع رو در قسمت دوم عرض کردم.

اما دوست عزیز جناب مشاطان یه توضیحی رو اینجا لازمه عرض کنم گرچه این مطلب ربط چندانی به مسئله نداره. Jump دو نوع نیست بلکه سه نوعه و تعریف انواع اون هم تقریبا چیز دیگریست از اونچه شما عرض کردید:



There are several variations of the jump instruction&#58;
_____________SHORT&#58;
This jump is very limited in range. It can only move up or down
128 bytes in memory. The advantage of this type is that it uses less
memory than the others. It uses a single signed byte to store the
displacement of the jump. The displacement is how many bytes to
move ahead or behind. &#40;The displacement is added to EIP&#41;. To specify
a short jump, use the SHORT keyword immediately before the label in
the JMP instruction.
_____________NEAR&#58;
This jump is the default type for both unconditional and conditional
branches, it can be used to jump to any location in a segment.
Actually, the 80386 supports two types of near jumps. One
uses two bytes for the displacement. This allows one to move up or
down roughly 32,000 bytes. The other type uses four bytes for the
displacement, which of course allows one to move to any location in
the code segment. The four byte type is the default in 386 protected
mode. The two byte type can be specified by putting the WORD keyword
before the label in the JMP instruction.
_____________FAR&#58;
This jump allows control to move to another code segment. This is a
very rare thing to do in 386 protected mode.

متن بالا از کتاب
PC Assembly Language
Paul A. Carter
December 12, 2002

Mashatan
دوشنبه 24 شهریور 1382, 10:47 صبح
دوست عزیزم آقا کامبیز دلیل استفاده از CMP بستگی به برنامه نویس داره. معمول اون پرش کردن در ادامه بلوک هست اما نه مطلق در جواب قبلیم این نوع رو در قسمت دوم عرض کردم.


میشه درباره این مورد یک مثال بزنید :wink:
مخصوصا قسمتی که به "برنامه نویس بستگی داره"



اما دوست عزیز جناب مشاطان یه توضیحی رو اینجا لازمه عرض کنم گرچه این مطلب ربط چندانی به مسئله نداره. Jump دو نوع نیست بلکه سه نوعه و تعریف انواع اون هم تقریبا چیز دیگریست از اونچه شما عرض کردید:


در مورد دوم حق با شماست من توی تعاریف جابجا نوشتم راستش من مثل شما از روی کتاب ننوشتم بلکه چیزی که یادم بود رو بیان کردم خیلی خوبه افرادی مثل شما هستند که از روی کتاب میخونند و اشکالات ما رو گوشزد میکنند :)
اصل کتاب
http://www.grid.unina.it/Didattica/CE/CEII/Iannello/docs/pcasm-book.pdf

ارادتمند
مشاطان

سه شنبه 25 شهریور 1382, 03:40 صبح
مثال بنده لازم نیست. شما اگر همون کتابی رو که آدرسش رو هم خوشبختانه دارید کمی خوب مطالعه کنید مکانیسم عمل CMP و JMP ها و خیلی چیزهای دیگه رو به خوبی درک میکنید و سوالهای درسی و بدیهی رو اینجا نمیپرسید.در ضمن یک مسئله دیگه بجای ایرادهای اینگونه ای و بیان تفکرات شخصی راجع به دستورات و نوع کاربرد اونها پیشنهاد میکنم به الگوریتم بدست آوردن مقادیر Max و Min که ارائه کردم کمی توجه کنید و اون رو به نقد بزارید. من زمانی که این کد رو نوشتم فکر میکردم که کسانی که این رو مطالعه میکنن توجهشون بیشتر به ساختمان اصلی بلوک هست و فرض بنده بر این بود که بدیهیاتی مانند اونهایی که در مورد Branch ها و ....ذکر کردم رو خواننده بدونه. به هر حال هر چه دوستان باب میلشون هست حتما همان صحیح است و روش ارائه شده از طرف بنده اشتباه و دفاع بنده از این روش در اینجا بیمعناست.

پیروز و شاد باشید

غریبه2
چهارشنبه 26 شهریور 1382, 10:29 صبح
سلام
آقا امید میشه با روشی که گفتی این دو متغیر را جابجا کنی :twisted:
int a,b
a=32000
b=1000
:?: :!: :idea:

(امید)
چهارشنبه 26 شهریور 1382, 12:10 عصر
سلام
آقا امید میشه با روشی که گفتی این دو متغیر را جابجا کنی :twisted:
int a,b
a=32000
b=1000
:?: :!: :idea:


a=a-b -->a=31000,b=1000
b=a+b ---> a=31000 , b=32000
a=b-a --->b=32000 , a=1000

(امید)
چهارشنبه 26 شهریور 1382, 12:20 عصر
علیرضا جان تابع ord رو می تونی سورسش رو تو خود دلفی ببینی.
راه حل خیلی قشنگیه ولی تابع integer هم IF داره ( بالای 30 تا :) )

:?: می شود بگویید داخل چه فایلی است؟ :cry:


کلید Ctrl رو نگه دار بعد با موس روی هر تابع که کلیک کنی سورسش رو می بینی . 8)

Adios

houshmand
چهارشنبه 26 شهریور 1382, 14:00 عصر
کلید Ctrl رو نگه دار بعد با موس روی هر تابع که کلیک کنی سورسش رو می بینی . 8)

آقا امید من این کار را برای Ord & Integer کردم ولی زیر این خط از یونیت system آمد :?: :!: :?: :cry: :cry:
unit System;

Kambiz
چهارشنبه 26 شهریور 1382, 14:20 عصر
دوستان، اینجا بخش الگوریتم هست. معنیش اینه که اگر قراره برای مسئله‌ای در اینجا راه حلی ارائه بشه٬ اون راه حل باید برای هر ماشین و هر زبان برنامه نویسی صادق باشه.

houshmand
چهارشنبه 26 شهریور 1382, 20:50 عصر
چون این بخش بخش الگریتم است :
در حالت کلی برای بدست آوردن بزرگ ترین عدد بین دو عدد از تابع زیر استفاده می کنیم


| a a>b
Max= |
| b b>a

یا


if a>b then max&#58;=a else max&#58;=b;

که این تابع قابل گسترش به


Max=a+b+|a-b|/2

است که اگر خوب دقت شود
معادل قدر مطلق x برابر ست با


y=|x|
if x>0 then Y&#58;=x else Y&#58;=-x;


/**************************************************


از بین دو عدد A و B کوچکترین و بزرگترین عدد را بدون استفاده از هرگونه مقایسه ضمنی یا عینی تعیین کنید.
اگر منظور این باشد که بدون هیچ عملیات دو شرطی کوچک ترین و بزرگترین این دو عدد را پیدا کنیم چین چیزی محال است و امکان ندارد


writeln&#40;'max=',&#40;2*a-&#40;&#40;a-b&#41; shr 31&#41;*2*&#40;a-b&#41;&#41; shr 1&#41;;
writeln&#40;'min=',&#40;2*b+&#40;&#40;a-b&#41; shr 31&#41;*2*&#40;a-b&#41;&#41; shr 1&#41;;

حتی در این هم دوشرطی وجود دارد
ولی این کار در داخل دستورات و روش نگهداری اعداد نهفته است
برای درک بهتر موضوع توجه کنید که معادل بیت علامت دو شرطی به صورت زیر قرار دارد
برای عدد x:


if x>0 then &#40;SightFlag off&#41; else &#40;SightFlag Set &#41;

و هر گز با عملیاتی مثل جمع و ضرب و or , and , xor , xnor ,....
:idea: بدون یک if نمیتوان این کار را کرد
البته از نوع ریاضی آن!


موفق باشید

Kambiz
چهارشنبه 26 شهریور 1382, 21:23 عصر
علیرضا جان یک دنیا ممنون. بدون ذره‌ای کم و کاست دلایلت برای من قابل قبوله.

seyedof
یک شنبه 26 بهمن 1382, 01:04 صبح
سلام
برای بدست آوردن ماکزیمم و مینیمم بدون شرط فرمولش همون قدر مطلق دار است اما اینطور که پیداست دعوا سر تابع قدر مطلق بدون پرش است خوب این هم بدون پرش و البته به زبان اسمبلی که کدش هم خیلی کوتاه است هم خیلی سریع :‌ (اینکه چجوری کار میکنه رو از توی منوال های اینتل بخونید) در ضمن روی سی پی یو های پنتیوم ۶ به بالا کار میکنه.

فرض که عدد صحیح علامتدار در رجیستر eax ریخته شده است خروجی شامل قدر مطلق هم در eax بازگردانده میشود :

mov eax,n
mov ebx,eax
neg ebx
or eax,eax
cmovs eax,ebx

ممنون
سیداف

Best Programmer
دوشنبه 27 بهمن 1382, 14:05 عصر
ببخشید یه کم کد شما اشتباه هست :wink:
اولا تمام جنگ ها بر سر این بود که if نداشته باشه ولی دستور CMOV(XX) eax,ebx دارای شرط میباشد. مراجعه شود به همون Manual صفحه 120 از manual دومی :wink:

seyedof
دوشنبه 27 بهمن 1382, 16:39 عصر
سلام

بله مشخصه که شرط داره اما شرطش در لول Microcode پیاده سازی شده و بسیار سریع انجام میشه. پرش هم نداره.
البته این روش بیشتر برای بهینه سازی سرعت مفیده :) حیف که تاپیکش مفقود الاثر شد ;) به هر حال یه روش tricky بود...

ممنون
سیداف

hooshmand_mostafa
سه شنبه 24 آذر 1383, 12:21 عصر
x&#58;=x+y;
y&#58;=x-y;
x&#58;=x-y;
:wink:

viviano
جمعه 05 فروردین 1390, 19:25 عصر
برای جابجا کردن دو تا متغیر با هر اندازه و هر نوعی:

A &lt;- A xor B
B &lt;- A xor B
A &lt;- A xor B

shaniaki جان بهتره موضوع جدید رو در تاپیک جدید عنوان کنیم.

ممکنه یکم در باره این کد توضیح بدی؟ نمی فهمم اون اشاره گر چیکار می کنه و به بعد

مسعود اقدسی فام
شنبه 06 فروردین 1390, 15:55 عصر
ممکنه یکم در باره این کد توضیح بدی؟ نمی فهمم اون اشاره گر چیکار می کنه و به بعد

اونها اشاره‌گر نیستن. علامت کوچکتر هستن:




A <- A xor B
B <- A xor B
A <- A xor B



یعنی A xor B را سه بار انجام بده و نتیجه رو به ترتیب در A و B و A قرار بده.