Программирование в школе

Методические заметки и задачи к урокам

Из портфолио учителя информатики и ИКТ     
Безрученко Людмилы Ивановны
e-mail:bezli@mail.ru     

   
  Условные конструкции  
  Циклы  
  Подпрограммы-функции
 
  Подпрограммы-процедуры
 
Назад

Раздел "Программирование"

Пользовательские функции

При вызове прдпрограммы-функции работа главной программы на некоторое время приостанавливается и начинает выполняться функция. Главная программа обычно передает функции какое-то конкретное знечение, указанное в главной программе. Этот параметр называется фактическим параметром, или аргументом. Он сопоставляется с некоторым формальным параметром, который является внутренним объектом подпрограммы.
На основе заданных величин вычисляется результат, который возвращается в главную программу как значение функции.

Структура подпрограммы-функции Подпрограмма-функция начинается с заголовка, в котором содержится имя функции, имя и тип каждого формального параметра, а также тип результата:

function <имя ф-ции>(<р1>:<тип_р1>;<р2>:<тип_р2>;... ):<тип_рез>;

Например, function sample(x:integer;y:real):real;
Здесь sample - имя функции, x,y - два формальных параметра, тип которых integer и real соответственно. Функция возвращает результат типа real.
В момент вызова подпрограммы значения аргументов - фактических параметров - сопоставляются с именами формальных параметров.
За заголовком функции следуют обявления локальных переменных подпрограммы-функции. Тело подпрограммы-функции заключается в операторные скобки begin - end;

Примечание. Необходимо помнить о следующих особенностях подпрограммы-функции:

  • Локальные переменные, объявленные в подпрограмме, никак не связаны с главной программой - глобальными переменнами - даже при совпадении имен (!).
  • в отличие от подпрограммы-процедуры подпрограмма-функция возвращает только одно значение;
  • тип этого результата должен быть указан в заголовке;
  • тип возвращаемого результата может относиться к простым (неструктурируемым) данным;
  • в теле функции должен обязательно присутствовать оператор вида
            <имя функции>:=<результат>
    т.е. имени функции присваивается окончательный результат, вычисляемый в подпрограмме;
  • ни один из параметров функции не должен быть var-параметром, так как ни один из них не должен получать новое значение в теле функции.
  • Преимущество использования подпрограмм-функций - возможность тестировать и отлаживать их независимо от других модулей.

    Где размещается подпрограмма-функция. В Паскале главная программа начинается с декларативной части (раздел объявлений типова данных), в которую, в частности, входят и описания всех подпрограмм.

    Как вызывается подпрограмма-функция. Пользвателские функции могут использоваться как в главной программе, так и в подпрограммах. При этом формальным параметрам должны быть поставлены в оответствие реальные параметры объявленные в главной программе.
    Например, пусть функция sxy(u,v:real):real; вычисляет сумму двух вещественных чисел, а в главной программе вычисляется с помощью с этой функции следующий фрагмент:
    begin...................
    readln (x,y);
    s:=sxy(10,5)/sxy(x,y);
    .........................
    end.
    В числителе функция sxy возвращает сумму (10+5), а в знаменателе функция sxy будет складывать два числа, которые вводятся с клавиатуры.

    Примеры пользовательских функций

    Пример 1. Функция sing возвращает знак вещественного числа.
      function sing(x:real):integer;
      begin
        if x=0 then sign:=0;
        if x>0 then sign:=1;
        if x<0 then sign:=-1;
      end;

    Пример 2. функция находит сумму квадратов первых n чисел:
    1*1+ 2*2+ 3*3+ 4*4+5*5+...n*n + ...
    function sumsqr(n:integer);
      var i:imteger;
    begin
      sum :=0;
      for i:=1 to n do
        sum:=sum + i*i;
      sumsqr:=sum
    end;{sumsqr}

    Пример 3. Функция находит наибольшее из трех целых чисел a,b,c.
    function max3(a,b,c:integer): integer;
      var
         max:integer; {условно наибольшее}
    begin
    {сначала находим наибольшее из a и b}
      if a > > =b   
         then max:=a
         else max:=b;
    {теперь сравним max с числом c}
      if max > > c
          then max3:=max
          else max:=c
    end; {max3}

    Пример 4. Во многих задачах возникает необходимость вычисления бесконечных рядов c заданной точностью с помощью рекуррентных соотношений.
    Рассмотрим эту проблему на примере вычисления суммы ряда
            S=x – x3/3! + x5/5! - x7/7! +... с заданной точностью eps.
    На первый взгляд задача может показаться достаточно сложной. Однако ситуация сильно упрощается, если использовать рекуррентную формулу, с помощью которой каждый последующий член ряда выражается через предыдущий., т.е. справедливо соотношение:
           un = q un-1
    Попробуем определить q, рассмотрев последовательно отношение второго члена к перовому, третьего ко второму, четвертого к третьему и т.д.:
          q1= u2 / u1 = - (x3/3!)/x = - x2/(2 * 3)
         q2= u3 / u2 = - (x5 / 5!) / (x3/3!) = - x2/(4 * 5)
         q3= u4 / u3 = - (x7 / 7!)/ (x5/ 5!) = - x/(6 * 7)
    ….......................................................
    Нетрудно видеть, что для произвольного q справедлива формула:
         q= - x2 / k/(k+1), где k= 2, 4, 6, ...
    Таким образом, положив первый член ряда равным x , можно вычислить следующий члена ряда, используя оператор:
         u:= - u* sqr(x)/k/(k+1);
    Ниже приводится подпрограмма-функция mysin(x) для вычисления ряда
    Вариант 1.

    Function mysin(x:real): real;
      const eps=0.00001; {точность вычиcления}
      var
         u: real; { член ряда}
        s: real; {сумма ряда}
         к : integer; {номер члена ряда}
    begin
      s:=0; {обнуление суммы}
      к:=0; {начальное значение переменной k}
      u:=x; {первый член ряда}
      while abs(u) > eps do {пока абсолютное значение члена ряда больше точности, выполняем}
        begin
          s:=s+u; {суммируем ряд}
          к:=к+2; { формируем четное число }
           u:= - u * sqr(x) / к/ (к+1) ; {вычисляем следующий член ряда}
        end;
      mysin:= s; {имени функции присваиваем результат s}
    end; {function}

    Пример 5. Задача о простых числах. Простым числом называется натуральное число, которое не имеет делителей - делится только на себя и на единицу. Функция выдает "флаг" f:=true; если число является простым.

    Вариант 1.
      function prost(j:word):boolean;
       var
        f:boolean; {"флаг"}
        m:word; {возможные делители}
      begin
          f:=true;{гипотеза, что число простое}
          {Проверка производится до первого делителя}
          m:=2; {первый возможный делитель}
          while (m <j) and f do
            begin
             if j mod m=0 then f:=false;
             m:=m+1
          end;{while}
      end;{prost}

    Вариант 2.Поскольку четные числа не простые, алгоритм рассматривает только нечетные числа. Для этого используется функция odd(j).

      function prost(j:word):boolean;
       var
        f:boolean; {"флаг"}
        m:word; {возможные делители}
        n:word;   begin
          f:=true;{гипотеза, что число простое}
          {Проверка производится до первого делителя}
       if odd(j) then {рассматриваем только нечетные числа}
          begin
           m:=1;
           n:=round(sqrt(j));
           repeat
             m:=m+2;
             if j mod m=0 then f:=false
           until f and (m>>=n)
           end
         else f:=false;
      end;{prost}

    Задание 1
    1. Напишите программу для вычисления sin(x) и mysin(x) при разной точности eps для значений x=pi/2 и pi/4 и занесите результаты в табличку:
    Eps sin x mysin(x)
    0.01 ... ...
    0.001 ... ...
    0.00001 ... ...

    Вывод. Для Sin(x) справедливо приближенное представление в виде бесконечного ряда:
          Sin(x) =x – x3/3! + x5/5! - x7/7! +...

    Контрольные вопросы

  • Как влияет значение eps на результат вычислений?
  • Можно ли использовать для решения этой задачи цикл repeat… until? Если да, то что изменится?

    Задание 2
    Проанализируйте приведенные ниже листинги функций и допишите комментарий.

    Function fsum(u:mas;n:integer):integer;
    {Суммирование элементов массива целых чисел}
      var
       i,s:integer;
    begin
      s:=0;   for i:=1 to n do
        s:=s+u[i];
      fsum:=s
    end; {fsum}

    Function fmin(u:mas;n:integer):integer;
    {Определение минимального элемента в массиве целых чисел}
      var
       i,s:integer;
    begin
      min:=u[i];   for i:=2 to n do
        if u[i]   fmin:=min
    end; {fmin}

    Function fmax(u:mas;n:integer):integer;
    {Определение максимального элемента в массиве целых чисел}
      var
       i,s:integer;
    begin
      max:=u[i];   for i:=2 to n do
        if u[i]>max then max:=u[i];
      fmin:=min
    end; {fmax}

    Function fsum_cifr(k:integer):integer;
    {Определение суммы цифр целого числа}
      var
       c,s:integer;
    begin
      s:=0;
      while n<>0 do    begin     s:=s+k mod 10;
        k:=k div 10
       end;
      fsum_cifr:=s
    end; {fsum_cifr}

  • Упражнения

    1. Укажите ошибки в заголовках функций:
    function ab(k:byte);
    function sgeron(a,b,c):integer;

    2.Составьте подпрограммы-функции

  • для расчета суммы кубов первых n чисел;
  • для расчета площади треугрльника по трем сторонам по формуле Герона.
    Примечание. При написании функции предусмотрите проверку существования треугольника.

    3. Напишите подпрограмму-функцию для вычисления суммы делителей целого положительного числа.

    4. Напишите подпрограмму-функцию для вычисления суммы и произведения цифр целого положительного числа.

    5. Напишите подпрограмму-функцию для определения, является ли число совершенным. Совершенное число - это число, которое равно сумме своих делителей, увеличенной на единицу. Например, совершенным является число 6: 2+3+1.