Рейтинг:  5 / 5

Звезда активнаЗвезда активнаЗвезда активнаЗвезда активнаЗвезда активна
 

Сейчас мы рассмотрим некоторые типовые задачи на подпрограммы, а после этого урока будет задания на эту тему.

1)

Описать процедуру Mean(x,y,Amean,Gmean), вычисляющую среднее арифметическое Amean = (x+y)/2 и среднее геометрическое Gmean = (x*y)^(1/2) двух положительных чисел x u y (x u y - входные, Amean, Gmean - выходные параметры вещественного типа). С помощью этой процедуры найти среднее арифметическое и среднее геометрическое для пары A, B.

Что касается моего мнения, то задание элементрарно. В нем уже даны все формулы для вычислений, сказаны, какие нужны параметры. Единственное, что нужно учесть - первые два параметра процедуры - положительные. Следовательно нужно поставить проверку на корректность входных данных.

Что касается способов передачи данных, то первые два параметра нужно передавать по значению, а последние два по ссылке. Единственное, что Вы не знаете, так это, как извлечь квадратный корень. На это есть функция sqrt, которая вычисляет квадратный корень из числа, а для возведения в квадрат есть в паскале функция sqr.

procedure Mean(x,y:real; var Amean,Gmean:real);

begin

  assert((x>=0) and (y>=0));

  amean:=(x+y)/2;

  gmean:=sqrt(x*y);

end;

begin

  var a,g:real;

  mean(readreal(),readreal(),a,g);

  writeln('A = ',a,' G = ',g);

end.

Этот код очень тривиален и по-моему, он не требует обьяснений.

2)

Описать процедуру AddRightDigit(d,k), добавляющую к целому положительному числу k справа цифру d (d - входной параметр целого типа, лежащий в диапазоне 1 - 9, K - параметр целого типа, являющийся входно-выходным). С помощью этой процедуры последовательно добавить к данному числу K справа данные цифры D1 u D2, выводя результат каждого добавления.

В этом задании тоже все сказано, что нужно сделать и как. Единственное что - это нужно будет в коде основной программы вызвать эту подпрограмму два раза. Очевидно, что первый параметр передаем по значению, а второй по ссылке.

procedure AddRightDigit(d:integer; var k:integer);

begin

  assert((d>0) and (d<10));

  k:=k*10+d;

end;

begin

  var k:integer:=readinteger();

  AddRightDigit(readinteger(),k);

  writeln('>> ',k);

  AddRightDigit(readinteger(),k);

  writeln('>> ',k);

end.

Опять же, этот код является элементарным и простым

3)

Описать процедуру ShiftRight3(A,B,C), выполняющую правый циклический сдвиг: значение А переходит в В, значение В - в С, значение С - в А (А, В, С - вещественные параметры, являющиеся входно-выходными). С помощью этой процедуры выполнить правый циклыческий сдвиг для двух данных наборов из трех чисел.

Здесь тоже все просто, единственное что - это немного запутано, но это задание вполне решаемо. Для решения нам понадобится процедура swap, которая меняет местами значения двух переменных и еще все.

Для решения нам нужно поменять местами с помощью процедуры swap первые две переменные. Тогда в А будет значение переменной В, а в переменной В - А. Первое условие мы этим выполним.

После этого нужно поменять значение переменных А и С. Тогда значение переменной А (а вней сидит значение переменной В) перейдет в переменную С, что выполнит 2 условие, а значение переменной С перейдет в переменую А, что выполнит последнее условие.

Остается это только запрограммировать, но в этом ничего сложного.

procedure ShiftRight3(var A,B,C:real);

begin

  swap(a,b);

  swap(a,c);

end;

begin

  var a,b,c:real;

  for var i:=1 to 2 do

  begin

    a:=readreal();

    b:=readreal();

    c:=readreal;

    write('A = ',a, ' B = ',b,' C = ',c);

    ShiftRight3(a,b,c);

    writeln(' >>> A = ',a, ' B = ',b,' C = ',c);

  end;

end.

4)

Описать функцию Quarter(x,y) целого типа, определяющую номер координатной четверти, в которой находится точка с ненулевыми вещественными координатами Х, У. С помощью этой функции найти номера координатных четвертей для трeх точек с данными ненулевыми координатами.

По условию, обе координаты должны быть отличными от 0, иначе будет трудно понять, какой четверти принадлежит точка. Для чевертей будем использовать слудующую нумерацию:

2

1

3

4

Для того, чтобы это запрограммировать нам потребуется assert, который проверит корректность данных, и 3 условных оператора в полной форме, которые определят четверт.

Мой алгоритм заключается в следующем:

1)проверяем входные данные на корректность

2)если Х>0, то

     2.1) Если Y>0 то это 1 четверть

     2.2)Если Y<0, то это 4 четверть

3) Если X<0, то

     3.1) Если Y>0 то это 2 четверть

     3.2)Если Y<0, то это 3 четверть

По-моему этот алгоритм вполне действенный и очень прост

function Quarter(x,y:real):integer;

begin

  assert((x<>0) and (y<>0));

  if (x>0) then

    if (y>0) then

      result:=1

    else

      result:=4

  else

    if (y>0) then

      result:=2

    else

      result:=3;

end;

begin

  for var i:=1 to 3 do

  begin

    var x,y:real;

    x:=readreal;

    y:=readreal;

    writeln('X = ',x,' Y = ',y,' >>> ',Quarter(x,y));

  end;

end.

5)

Описать функцию IsPrime(N) логического типа, возвращающую True, если целый параметр N (> 1) является простым числом, и False в противном случае (число, большее 1, называется простым, если оно не имеет положительных делителей, кроме 1 и самого себя).

Здесь все просто: в подпрограмме нужно сделать цикл, который будет определять делимость числа на другие числа. И, если будет найден такой делитель, то число не простое.

Я сразу сделаю одну оптимизацию: если хорошо подумать, то мы не сможем найти хотя бы один делитель в диапазоне от (x/2+1) до x. При делении в данном диапазоне мы получим дробное число, либо 1. В любом случае нам это не подходит, а такая оптимизация сильно сократит время работы программы

Что касается проверки на делимость, то для этого нам пригодится оператор mod. Если остаток от деления равен 0, то это число не простое, следовательно нужно завершать подпрограмму. Если не будет найден делитель, то число простое.

function IsPrime(n:integer):boolean;

begin

  assert(n>0);

  result:=true;

  for var i:=2 to (n div 2)+1 do

  begin

    result:=(n mod i)<>0;

    if not result then

      exit;

  end;

end;

begin

  for var i:=1 to 10 do

  begin

    var x:integer;

    x:=readinteger();

    writeln(x,' >>> ',IsPrime(x));

  end;

end.

6)

Описать функцию DigitN(K, N) целого типа, возвращающую N-ю цифру (N>0) целого числа K (цифры в числе нумеруются справа налево). Если количество цифр в числе K меньше N, то функция возвращает −1.

Здесь тоже все элементарно. Нужно в подпрограмме реализовать цикл, который будет идти по цифрам числа и в нужный момент он должен остановиться. При после цикла нужно реализовать проверку на то, что число равно 0. Если получившееся число равно 0, значить в числе нет такой цифры n. Если же не равно, то его нужно возвратить.

При этом нужно учесть, что возвращаемое значение - цифра, а цифры бывают только положительными. Поэтому нам пригодится функция abs, которая берет значение числа по модулю (делает его положительным).

function DigitN(K, N:integer):integer;

begin

  assert(n>0);

  k:=abs(k);

  for var i:=2 to n do

    k:=k div 10;

  if (k=0) then

    result:=-1

  else

    result:=k mod 10;

end;

begin

  writeln('Result = ',Digitn(readinteger(),readinteger()));

end.

7)

Описать функцию Fact2(N) вещественного типа, вычисляющую двойной факториал:
N!! = 1·3·5·…·N, если N — нечетное;
N!! = 2·4·6·…·N, если N — четное

(N > 0 — параметр целого типа;вещественное возвращаемое значение используется для того, чтобы избежать целочисленного переполнения при больших значениях N). С помощью этой функции найти двойные факториалы пяти данных целых чисел.

Вполне очевидно, что для решения данного задания нам поторебуется цикл while. И что касается моего мнения, то это задание очень простое. Только нужно не забыть о проверке на корректность входного параметра.

Смысл алгоритма: идем циклом пока параметр n>0 (поскольку он передан по значению, то ничего страшного не случится). Внутри цикла мы умножаем результат функции (при этом до цикла этому значению я присваиваю 1, чтобы не потерять найденное значение) на текущее найденное значение, после чего оно уменшается на 2. Тем самым это обеспечит четность или нечетность значений.

function Fact2(N:integer):real;

begin

  assert(n>0);

  result:=1;

  while n>0 do

  begin

    result*=n;

    n-=2;

  end;

end;

begin

  for var i:=1 to 5 do

  begin

    var x:integer:=readinteger();

    writeln(x,' >>> ',Fact2(x));

  end;

end.

8)

Описать процедуру TimeToHMS(T, H, M, S), определяющую по времени T (в секундах, T≥0) содержащееся в нем количество часов H, минут M и секунд S (T — входной, H, M иS — выходные параметры целого типа). Используя эту процедуру, найти количество часов, минут и секунд для пяти данных отрезков времени T1, T2, …, T5.

Это задание очень простое. Оно выполняется с помощью двух операторов mod и двух операторов div.

Поскольку нам дано время в секундах, то нам нужно это время максимально поделить на 60 (перевести его в минуты), а остаток взять в качестве возвращаемого значения - секунд. То же самое нужно делать с минутами.

Опять же нужно проверить входные данные на корректость.

procedure TimeToHMS(T:integer;var H, M, S:integer);

begin

  assert(t>0);

  s:=t mod 60;

  t:=t div 60;

  m:=t mod 60;

  t:=t div 60;

  h:=t;

end;

begin

  for var i:=1 to 5 do

  begin

    var x:integer:=readinteger();

    var h,m,s:integer;

    TimeToHMS(x,h,m,s);

    writeln(x, ' >>> H = ',h,' M = ',m,' S = ',s);

  end;

end.

9)

Описать процедуру IncTime(H, M, S, T), которая увеличивает на T секунд (T≥0) время, заданное в часах H (>=0), минутах M (>=0) и секундах S (>=0)
Здесь H, M иS — входные и выходные параметры, T — входной параметр.
Дано время (в часах H, минутах M, секундах S) и целое число T. Используя процедуру IncTime, увеличить данное время на T секунд и вывести новые значения H, M, S.

К этому заданию есть два подхода:

1) прибавить сразу время к секундам, а потом уже переводить время к нормальному формату

2) перевести все в секунды, добавить время и воспользоваться подпрограммой из предыдущего задания.

Я обьяснил, что нужно сделать во втором способе, да и он очень простой для выполнения, поэтому пойду 1 путем.

Несмотря на то, какой Вы выбрали способ, нужно обязательно сделать проверку входных данных.

А вообще эта подпрограмма очень похожа на подпрограмму из предыдущего задания.

Алгоритм:

1)проверить на корректность все входные данные

2) прибавить к секундам нужное время

3) перевести секунды в минуты, если это возможно, и прибавить получившееся значение к текущим минутам.

4) пересчитать секунды.

5) повторить шаги 3 и 4 для минут

procedure IncTime(var H, M, S:integer; t:integer);

begin

  assert(t>0);

  assert((h>0) and (m>0) and (s>0));

  assert((s<60) and (m<60));

  s+=t;

  t:=s div 60;

  s:=s mod 60;

  m+=t;

  h+=m div 60;

  m:=m mod 60;

end;

begin

  var h,m,s,t:integer;

  h:=readinteger();

  m:=readinteger();

  s:=readinteger();

  t:=readinteger();

  inctime(h,m,s,t);

  writeln('H = ',h,' M = ',m,' S = ',s);

end.

10)

Описать функцию IsLeapYear(Y) логического типа, которая возвращает True, если год Y (целое положительное число) является високосным, иFalse в противном случае. Вывести значение функции IsLeapYear для пяти данных значений параметра Y. Високоснымсчитается год, делящийся на 4, за исключением тех годов, которые делятся на 100 и не делятся на 400.

Задача очень проста. Нужно всего-навсего запрограммировать подпрограмму, которая проверит делимость полученного значения на 4. Если оно не делится, то нужно завершить подпрограмму. Если делится, то нужно проверить 2 условие: делимость на 400, если исходный год делится на 100.

Что касается моего мнения, то здесь понадобится 2 условных оператора и три оператора mod.

Вначале проверяем делимость на 4. Если год делится на 4, тогда проверяем его делимость на 100. Если он делится на 100, то проверяем его делимость на 400.

function IsLeapYear(Y:integer):boolean;

begin

  assert(y>0);

  result:=(y mod 4)=0;

  if (result) then

    if (y mod 100)=0 then

      result:=(y mod 400)=0;

end;

begin

  writeln(isleapyear(readinteger()));

end.

В следующем уроке будет набор заданий, которые мы рекомендуем выполнить. Для их выполнения скачайте последнюю версию PascalABC.NET и выполняйте задания. После того, как Вы выполните все задания, загружайте их на страницу и ждите, пока оно не будет проверено. После проверки Вы получите сообщение на свой адрес электронной почты с результатом. Никто, кроме Вас, не будет знать о результатах. (для сохранения конфиденсальной информации необходима регистрация).