Rekursiv kamayish usuli - Tiplarni dinamik tarzda

|
Tiplarni dinamik tarzda
|
bet | 62/131 | Sana | 16.06.2024 | Hajmi | 1,92 Mb. | | #264063 |
Bog'liq Tiplarni dinamik tarzdaRekursiv kamayish usuli. Eng oddiy va juda ko‘p foydalanilgan past sathlarga yo‘naltirilgan analizatorlarni qurish usuli rekursiv kamayish usulidir (recursive descent method).
Rekursiv kamayish usuli asosiy tamoyillarini o‘rganish uchun arifmetik ifodalarni bajarilish masalasini qaraymiz. Ularga binar amallari qo‘shish (+), ayrish (-), ko‘pytirish (*), butun bo‘lish (/) va qavslar amallari kirsin. Odatdagidek, ko‘paytirish va bo‘lish amallarining ustivorligi teng va ularning ustivorligi qo‘shish va ayirish amallarining ustivorligidan katta bo‘lib, bu amallarning ustivorligi ham tengdir. Qo‘shish turidagi amallarga (+) va (-) - amallarini, ko‘paytirish turidagi amallarga esa (*) va (/) - amallari qilib belgilaymiz. Qavslar amali standari tartibini o‘zgartirish uchun ishlatiladi. Vazifamiz ifoda qiymatini hisoblovchi dastur yozishdan iborat.
Qaralayotgan ifodani quyidagi ko‘rinishda bo‘lsin
T1 +T2 +…+Tn
Bunda Ti - F1i *F2i *…*Fmi ko‘rinishidagi ifoda. Shuningdek, Fji – bu son yoki qavs ichidagi ifoda.
Berilgan ifodani hisoblash jarayonini o‘ylab ko‘ramiz, bunda birinchi galda F11 hisoblanadi va F11 dan keyin qaysi amal turganini aniqlanadi. Agar bu ko‘paytirish amali bo‘lsa, chap operandini bilib, o‘ng operandini aniqlaymiz va amalni bajaramiz. Shunday qilib, ko‘paytirish amali uchun chap operandani aniqlaymiz. F1*F2*…*Fn amallar ketma ketligini hisoblab bo‘lgandan keyin, keyingi amal sifatida bo‘lish
amalini kelsa, buni ham yuqoridagi jarayon bo‘yicha hisoblaymiz.
Ifodalarni hisoblashda barcha hisoblashlarni quyidagi sinflarga ajratish mumkin:
Oddiy ifoda, sonlar va qavslar bilan berilgan chiziqli ifodalar, masalan, 28, (128-25+16);
Ifoda, ko‘paytirish tipidagi amallari bo‘lgan ifoda, ko‘paytirish va bo‘lish amallari kiradi, maslan, 2*15, 28*(15/3)+3;
Ifoda, qo‘shish tipidagi amallari bo‘lgan ifoda, qo‘shish va ayirish amallari kiradi, masalan, 5-3, (5*3)/10-2;
Bular asosida hisoblash jarayonini tasavur qilishimiz mumkin va quyidagi formula bilan ifodalaymiz.
-
Expression (Term (Factor ()));
|
Bunda Factor – oddiy ifodani hisoblash protsedurasi bo‘lib, son, qavslarga ega chiziqli ifoda, Term - ko‘paytirish amali tipidagi amallarni saqlovchi ifoda qiymatini hisoblash protsedurasi, Expression - qo‘shish amali tipidagi amallarni saqlovchi ifoda qiymatini hisoblash protsedurasi.
Oddiy ifodani hisoblash protsedurasi:
-
int Factor ()
{char ch = getChar();
if (isDigit (ch)) return getValue(ch); if (ch == '(')
{int result = Formula();
if (getChar() == ')') return result; error ("kutilmagan belgi yoki amal"); return 0;
}
return error ("kutilmagan belgi yoki amal"); }
|
Dastur ko‘paytirish tipiga oid amallarni hisoblash uchun ifodani tahlil qiladi. Ko‘paytirish tipiga oid amallarni hisoblash uchun ifodani hisoblashning umumiy formulasi quyidagicha:
F1*F2*…*Fn
Aniq tushunishimiz keraki, hisoblash bajarilayotgan amallar faqat ko‘paytirish yoki bo‘lishi amali bo‘ladi. Bunday amallarni hisoblash uchun Term protsedurasini yaratish mumkin. Bu protseduraning parametrlari butun sonili qiymatlar bo‘lishi kerak. Bunda chap operandani tanlashimiz va kerakli amalni bajarish uchun son yoki oddiy ifodadan iborat o‘ng operandani aniqlashimiz lozim, so‘ng esa amalni bajarish mumkin. Buni quyidagi dastur fragmenti asosida amalga oshirishsh mumkin.
int Term (int left)
{char ch = getChar(); int right; if (ch != '*' && ch !='/')
{
/* navbatdagi amal kutilmagan boʻlsa, uni qaytarishmiz kerak*/ returnChar(); /*kutimagan belgini qaytarish */
return left; /*kutilmagan qimatni qaytarish */
}
/* Hammasi yaxshi boʻlsa, oʻng operandni aniqlah kerak*/ right = Factor();
if (ch == '*')
{return Term(left * right);
/* bu hisoblashni bajarishni aniqlaydi */
}
if (right == 0) return error ("Nolga boʻlinish"); return Term(left / right);
}
Dastur qo‘shish tipiga oid amallarni hisoblash uchun ifodani tahlil qiladi. Qo‘shish tipiga oid amallarni hisoblash uchun ifodani hisoblashning umumiy formulasi quyidagicha:
T1 +T2 +…+Tn
Aniq tushunishimiz keraki, hisoblash bajarilayotgan amallar faqat qo‘shish yoki ayirish amali bo‘ladi. Bunday amallarni hisoblash uchun Expression protsedurasini yaratish mumkin. Bu protseduraning parametrlari butun sonili qiymatlar bo‘lishi kerak. Bunda chap operandani tanlashimiz va kerakli amalni bajarish uchun son yoki oddiy ifodadan iborat o‘ng operandani
aniqlashimiz lozim, so‘ng esa amalni bajarish mumkin. Buni quyidagi dastur fragmenti asosida amalga oshirishsh mumkin.
Yuqoridagi protseduralar ishlashi uchun quyidagi usullarni mustaqil ishlab chiqish kerak. Umuman olganda rekursiv kamayish usuli qiziqtirgan edi, o‘ylaymizki, quyidagi fragmentlarni yaratsangiz bunga ishonch hosil qilasiz.
Kirish oqimidan navbatdagi belgini kutuvchi, getChar parametrsiz usuli.
Kutilmagan belgini kirish oqimiga chiqarib berish returnChar usuli.
isDigit i getValue usullarni ham yozish shartmas. Agar parametri son bo‘lsa, birinchi usul true qaytaradi. Ikkinchi usul esa parametr sifatida kirish oqimidan berilan satrdan sonlarni ajratib oladi va butun qiymatlarni hisoblaydi.
Error usuli xatolar haqidagi xabarlarni chiqarish uchun ishlatiladi.
Bu usullarni mustaqil hal qilish mumkin, ammo .NET standart sinflar usullari asosida baʻzalarini modifikatsiyalab yaratish mumkin. Bu dasturlar fragmentini shakllantirishda qiymat qaytarish asosidagi rekursiv kamayish usulidan foydalanildi (recursive descent with backtracking). Qiymat qaytarmaslik asosidagi rekursiv kamayish usuli bilan chegaralanib qolmaganimizni ko‘rib chiqamiz.
|
| |