Συναρτησιακός προγραμματισμός

Διομήδης Σπινέλλης
Τμήμα Διοικητικής Επιστήμης και Τεχνολογίας
Οικονομικό Πανεπιστήμιο Αθηνών
dds@aueb.gr

Συναρτησιακές παράμετροι

Μπορούμε να ορίσουμε ως ορίσμα μιας διαδικασίας ή συνάρτησης μια άλλη διαδικασία ή συνάρτηση αρκεί να ορίσουμε τον αντίστοιχο τύπο.

Παράδειγμα:

program maptest;
{$F+}
type
	realmap = function(x : real) : real;

function map2(f : realmap; n : real) : real;
begin
	map2 := f(f(n))
end;

function double(x : real) : real;
begin
	double := x * 2
end;

begin
	writeln(map2(double, 1))
end.
Το πρόγραμμα θα υπολογίσει την τιμή double(double(1)) και θα τυπώσει 4.

Σημείωση

Στην Turbo Pascal 7.0 πρέπει στην αρχή του προγράμματος να δωθεί το σχόλιο {$F+} για να υποστηριχτεί η λειτουργία αυτή.

Η συνάρτηση map

Η διαδικασία map μετασχηματίζει μια σειρά στοιχείων σε μια άλλη, με βάση μια συνάρτηση από στοιχείο σε στοιχείο. Αν η συνάρτηση είναι η f και η σειρά αποτελείται από τα στοιχεία:
σ1, σ2, σ3, σ4, σ5 ...
τότε η νέα σειρά θα είναι:
f(σ1), f(σ2, f(σ3), f(σ4), f(σ5) ...

Για παράδειγμα με βάση τη διαδικασία map και αντίστοιχη συνάρτηση f μπορούμε εύκολα να δημιουργήσουμε από έναν πίνακα v έναν νέο πίνακα v' του οποίου τα στοιχεία να είναι διπλάσια κάθε στοιχείου του v:

program Map;
{$F+}
const
	maxindex = 10;

type
	realmap = function(x : real) : real;
	mylist = array [1..maxindex] of real;

var
	i : integer
	l1, l2 : mylist;

procedure map(f : realmap; v : mylist; var vnew : mylist);
var
	i : integer;
begin
	for i := 1 to maxindex do
		vnew[i] := f(v[i])
end;

function double(x : real) : real;
begin
	double := x * 2
end;

begin
	for i := 1 to maxindex do
		readln(l1[i]);
	map(double, l1, l2);
	for i := 1 to maxindex do
		writeln(l2[i]);
end.

Η συνάρτηση fold

Η συνάρτηση fold "διπλώνει" μια σειρά στοιχείων σε μια τιμή με βάση μια συνάρτηση από στοιχείο και τιμή σε τιμή και μια αρχική τιμή. Αν η συνάρτηση είναι η f, η αρχική τιμή α και η σειρά αποτελείται από τα στοιχεία: σ1, σ2, σ3 ... τότε η νέα σειρά θα είναι: f(...,f(σ3, f(σ2, f(σ1, α))))...

Για παράδειγμα με βάση τη συνάρτηση fold και αντίστοιχη συνάρτηση f μπορούμε εύκολα να βρούμε το άθροισμα των στοιχείων ενός πίνακα:

program TestFold;
{$F+}
const
        maxindex = 10;
type
        realmap = function(x : real; y : real) : real;
        mylist = array [1..maxindex] of real;
var
        i : integer;
        l : mylist;
function fold(f : realmap; a : real; v : mylist) : real;
var
        i : integer;
        result : real;
begin
        result := a;
        for i := 1 to maxindex do
                result := f(v[i], result);
        fold := result;
end;
function sum(x : real; y : real) : real;
begin
        sum := x + y
end;
begin
        for i := 1 to maxindex do
                readln(l[i]);
        writeln(fold(sum, 0, l))
end.

Αριθμητικές μέθοδοι

Με βάση συναρτησιακές παραμέτρους μπορούμε να υλοποιήσουμε παραμετρικά διάφορες αριθμητικές μεθόδους. Τα παρακάτω παραδείγματα αν και απλοϊκά ως προς τις τεχνικές και τις μεθόδους υλοποίησης δείχνουν τον τρόπο της παραμετρικής χρήσης συναρτησιακών παραμέτρων.

Εύρεση ρίζας εξίσωσης με τη μέθοδο Newton-Raphson

Μπορούμε να επιλύσουμε μια εξίσωση της μορφής f(x) = 0 με βάση την επαναλαμβανόμενη εφαρμογή του

μέχρι η διαφορά μεταξύ δύο εφαρμογών να γίνει αρκετά μικρή. Η αρχική τιμή που χρησιμοποιούμε είναι απλώς μια υπόθεση.

Η εύρεση της παραγώγου f' της f για μια τιμή x μπορεί και αυτή να υπολογιστεί αριθμητικά ως:

για μια αρκετά μικρή τιμή του h.

Το παρακάτω πρόγραμμα βρίσκει αριθμητικά μια ρίζα (1.4142135624) της εξίσωσης x^2 - 2 = 0.

program NewtonRaphsonExample;
{$F+}
const
     Epsilon = 1e-8;	{Αρκετά μικρή τιμή}

type
    realfun = function(x : real) : real;

{Εύρεση παραγώγου της f για την τιμή x}
function DerivativeValue(f : realfun; x : real) : real;
begin
     DerivativeValue := (f(x + epsilon) - f(x)) / epsilon
end;

{Εύρεση ρίζας της f για αρχική πιθανή τιμή x}
function NewtonRaphson(f : realfun; x1 : real) : real;
var
   x0 : real;
begin
     repeat
           x0 := x1;
           x1 := x0 - f(x0) / DerivativeValue(f, x0)
     until abs(x1 - x0) < epsilon;
     NewtonRaphson := x1
end;

{Εξίσωση - παράδειγμα (χ^2 - 2 = 0)}
function Example(x : real) : real;
begin
     Example := sqr(x) - 2
end;

begin
     writeln(NewtonRaphson(Example, 12))
end.

Αριθμητικός υπολογισμός ολοκληρώματος με τη μέθοδο του τραπεζίου

Χωρίζοντας την επιφάνεια που ορίζει μια συνάρτηση σε μεγάλο αριθμό τραπεζίων μπορούμε να προσεγγίσουμε αριθμητικά την τιμή του ολοκληρώματος:

ως άθροισμα των εμβαδών τους. Το όρισμα μιας τέτοιας συνάρτησης είναι της μορφής:
Function Integrate(f : realfun; a, b : real) : real;

Βιβλιογραφία

Ασκήσεις

Pascal 11

  1. Να γραφεί πρόγραμμα σε Pascal το οποίο να υπολογίζει με τη μέθοδο του τραπεζίου το ολοκλήρωμα μιας συνάρτησης. Με βάση το πρόγραμμα αυτό να υπολογιστεί η τιμή Α του

    και να τυπωθεί το Α και το 4*Α.

    Ο υπολογισμός του ολοκληρώματος να γίνει σε ξεχωριστή συνάρτηση με παραμέτρους τη συνάρτηση για την οποία θα υπολογιστεί το ολοκλήρωμα, καθώς και τα άνω και κάτω όρια, α και β.

Περισσότερες λεπτομέρειες για τις ασκήσεις