Направете функции, които извършват аритметичните операции събиране, изваждане, умножение и целочислено деление между две обикновени дроби, подадени като параметри. В главната програма с помощта на тези функции пресметнете изразите:
- 2/3 + 3/4 =
- 4/5 – 3/6 =
- 1/6 * 25/4 =
- 25/4 : 2/ =
По желание: Да се добавят и функции, които проверяват дали дробта е правилна или неправилна, за представянето на неправилните дроби като смесени числа и за съкращаване на числителя и знаменателя доколкото е възможно.


„4. 25/4 : 2/колко =“ направил съм го с 2/1. За целочисленото делене не съм сигурен дали така трябва да се направи :D
Калояне, целта на тази задача е да се направят функции, които извършват операциите с обикновени дроби, като ги запазват като обикновени (с числител и знаменател), а не да ги превръщат в десетични. Например умножението би трябвало да бъде така: ако a3/b3 = a1/b1 * a2/b2, то a3=a1*a2 и b3=b1*b2 Тоест за да намерим числителя и знаменателя на резултата, умножаваме числителите и знаменателите на двете дроби.
procedure sakrashtavane(var a3,b3:integer; var ch:real);//Процедура за съкращаване на дробите var i:integer; begin if a3>b3 then ch:=a3/b3 else if a3<=b3 then for i:=b3 downto 1 do if a3 mod i = 0 then if b3 mod i = 0 then begin a3:=a3 div i; b3:=b3 div i; end; end; //Събиране procedure sabirane(out a3,b3:integer; out ch:real); var a1,b1,a2,b2,i:integer; begin a1:=2; b1:=3; a2:=3; b2:=4; //Пресмятаме като дроб a3:=((b2*a1)+(b1*a2)); b3:=b1*b2; sakrashtavane(a3,b3,ch);//Извъкваме процедурата за съкращаване end; //Изваждане procedure izvajdane(out a3,b3:integer; out ch:real); var a1,b1,a2,b2,i:integer; begin a1:=4; b1:=5; a2:=3; b2:=6; //Пресмятаме като дроб a3:=((b2*a1)-(b1*a2)); b3:=b1*b2; sakrashtavane(a3,b3,ch);//Извъкваме процедурата за съкращаван end; //Умножение procedure umnojenie(out a3,b3:integer; out ch:real); var a1,b1,a2,b2,i:integer; begin a1:=1; b1:=6; a2:=25; b2:=4; //Пресмятаме като дроб a3:=a1*a2; b3:=b1*b2; sakrashtavane(a3,b3,ch);//Извъкваме процедурата за съкращаван end; //Делене procedure delene(out a3,b3:integer; out ch:real); var a1,b1,a2,b2,i:integer; begin a1:=25; b1:=4; a2:=2; b2:=1; //Пресмятаме като дроб a3:=a1*b2; b3:=b1*a2; sakrashtavane(a3,b3,ch);//Извъкваме процедурата за съкращаван end; VAR a3,b3:integer; ch:real; BEGIN //Събиране sabirane(a3,b3,ch); if a3<=b3 then writeln(a3,'/',b3) else if a3>b3 then writeln(ch:0:2); //Изваждане izvajdane(a3,b3,ch); if a3<=b3 then writeln(a3,'/',b3) else if a3>b3 then writeln(ch:0:2); //Умножение umnojenie(a3,b3,ch); if a3<=b3 then writeln(a3,'/',b3) else if a3>b3 then writeln(ch:0:2); //Делене delene(a3,b3,ch); if a3<=b3 then writeln(a3,'/',b3) else if a3>b3 then writeln(ch:0:2); readln; END.//Проверка дали дробта е правилна или неправилна function proverka(a3,b3:integer):boolean; begin if a3<=b3 then result:=true//Правилна else if a3>b3 then result:=false//Неправилна end; //Процедура за съкращаване procedure sakrashtavane(var a3,b3:integer);//Процедура за съкращаване на дробите var i,max:integer; begin if a3>b3 then max:=a3 else max:=b3; for i:=2 to max do if a3 mod i = 0 then if b3 mod i = 0 then begin a3:=a3 div i; b3:=b3 div i; end; end; //Превръщане в смесено число procedure smeseno(const a3,b3:integer; var a,b,c:integer); begin if not(proverka(a3,b3)) then a:=a3 div b3;//Цяла част b:=a3-(a*b3);//Числител c:=b3;//Знаменател end; //Събиране procedure sabirane(const a1,b1,a2,b2:integer; out a3,b3,a,b,c:integer); var i:integer; begin a3:=((b2*a1)+(b1*a2)); b3:=b1*b2; sakrashtavane(a3,b3);//Извъкваме процедурата за съкращаване if not(proverka(a3,b3)) then smeseno(a3,b3,a,b,c); end; //Изваждане procedure izvajdane(const a1,b1,a2,b2:integer; out a3,b3,a,b,c:integer); var i:integer; begin a3:=((b2*a1)-(b1*a2)); b3:=b1*b2; sakrashtavane(a3,b3);//Извъкваме процедурата за съкращаванe if not(proverka(a3,b3)) then smeseno(a3,b3,a,b,c); end; //Умножение procedure umnojenie(const a1,b1,a2,b2:integer; out a3,b3,a,b,c:integer); var i:integer; begin a3:=a1*a2; b3:=b1*b2; sakrashtavane(a3,b3);//Извъкваме процедурата за съкращаванe if not(proverka(a3,b3)) then smeseno(a3,b3,a,b,c); end; //Делене procedure delene(const a1,b1,a2,b2:integer; out a3,b3,a,b,c:integer); var i:integer; begin a3:=a1*b2; b3:=b1*a2; sakrashtavane(a3,b3);//Извъкваме процедурата за съкращаванe if not(proverka(a3,b3)) then smeseno(a3,b3,a,b,c); end; VAR a1,b1,a2,b2,a3,b3,a,b,c:integer; BEGIN //Събиране sabirane(2,3,3,4,a3,b3,a,b,c); if proverka(a3,b3) then writeln(a3,'/',b3) else writeln(a,' ',b,'/',c); //Изваждане izvajdane(4,5,3,6,a3,b3,a,b,c); if proverka(a3,b3) then writeln(a3,'/',b3) else writeln(a,' ',b,'/',c); //Умножение umnojenie(1,6,25,4,a3,b3,a,b,c); if proverka(a3,b3) then writeln(a3,'/',b3) else writeln(a,' ',b,'/',c); //Делене delene(25,4,2,1,a3,b3,a,b,c); if proverka(a3,b3) then writeln(a3,'/',b3) else writeln(a,' ',b,'/',c); readln; END.Браво, голям напредък по задачата! Почти си на финала! Процедурата smeseno обаче не ми харесва – ако дробта е правилна, няма да се запише нищо в параметрите a,b,c. И няма как да се разбере дали там ще има нещо или не, освен да се вика проверка. Тоест тази функция понякога работи, а понякога не. Добрата функция е като инструмент (като тесла или лопата например – винаги работи :-) За мен по-добро решение щеше да бъде ако когато дробта е правилна, за цялата част се връща 0. Тогава и функциите за събиране, изваждане, умножение и деление ще станат по-прости и само с 3 изходящи параметъра. Дори аз бих ги направил с два, за да връщат само числителя и знаменателя на резултата – защо винаги да преобразуват към смесени числа – може това понякога да не е желано (например ако ще продължим със следващи изчисления с дробите, получени като резултат). И накрая бих направил една функция за печат на дроби, която проверява дали дробта е правилна или неправилна и евентуално отпечатва неправилната дроб като смесено число. Така и главната програма ще стане по-проста.
Има някои прости препоръки, които трябва да се знаят за писане на „добри“ функции:
1. Една функция прави едно нещо
2. Една функция винаги връща резултат
3. Ако има повторения в кода, значи може да се заменят с функция
И малко обяснение по 1: ако функцията прави много неща, първо тя става сложна като код, има повече вероятност за грешки в нея, от извикването и не може да се разбере коя от всичките си функции изпълнява и, понеже прави какво ли не, вероятно ще се извиква от много места в програмата и при промяна на функцията има по-голям шанс за прецакване на програмата на много места :-) Ако функцията е проста и прави едно нещо, всички изброени по-горе недостатъци се избягват.
//Проверка дали дробта е правилна или неправилна function proverka(a,b:integer):boolean; begin if a<=b then result:=true//Правилна else if a>b then result:=false//Неправилна end; //Процедура за съкращаване procedure sakrashtavane(var a,b:integer); var i,max:integer; begin if a>b then max:=a else max:=b; for i:=max downto 2 do if a mod i = 0 then if b mod i = 0 then begin a:=a div i; b:=b div i; end; end; //Превръщане в смесено число procedure smeseno(var a,b,c:integer); var x,y:integer; begin if proverka(a,b) then c:=0 else begin x:=a; y:=b; c:=x div y;//Цяла част a:=x-(c*y);//Числител b:=y;//Знаменател end; end; //Събиране procedure sabirane(const a1,b1,a2,b2:integer; out a,b:integer); begin a:=((b2*a1)+(b1*a2)); b:=b1*b2; sakrashtavane(a,b); end; //Изваждане procedure izvajdane(const a1,b1,a2,b2:integer; out a,b:integer); begin a:=((b2*a1)-(b1*a2)); b:=b1*b2; sakrashtavane(a,b); end; //Умножение procedure umnojenie(const a1,b1,a2,b2:integer; out a,b:integer); begin a:=a1*a2; b:=b1*b2; sakrashtavane(a,b); end; //Делене procedure delene(const a1,b1,a2,b2:integer; out a,b:integer); begin a:=a1*b2; b:=b1*a2; sakrashtavane(a,b); end; //Процедура за превръщане на дробта в смесено число(ако е нужно) и отпечатване procedure pechat(a,b,c:integer); begin smeseno(a,b,c); if c<>0 then writeln(c,' ',a,'/',b) else writeln(a,'/',b); end; VAR a1,b1,a2,b2,a,b,c:integer; BEGIN //Събиране sabirane(2,3,3,4,a,b); pechat(a,b,c); //Изваждане izvajdane(4,5,3,6,a,b); pechat(a,b,c); //Умножение umnojenie(1,6,25,4,a,b); pechat(a,b,c); //Делене delene(25,4,2,1,a,b); pechat(a,b,c); readln; END.Перфектно! Мисля, че вече знаеш малко повече по въпроса каква е ползата от функциите и как да употребяваш ефективно параметрите им :-)
Ако лятото качваш решения и по задачите от предишни години, при първа възможност ще ги преглеждам и ако имам забележки ще ти пиша. Иначе само ще ги одобрявам. Другият вариант е да решаваш задачи от сайта, който ти казах, или да разгледаш архивите на форума по информатика (регистрирай се там, пиши кой потребител си и ще ти дам пълни права да виждаш всичко и да публикуваш).