You are on page 1of 54

Introduzione a MAPLE

Andrea Ellero, Alberto Zorzi - AA.2002/2003

Questi appunti hanno lo scopo di introdurre alluso del programma Maple


(Waterloo Maple Inc.) e sono di supporto alle lezioni di Informatica (idoneit`
a),
Facolt`
a di Economia dellUniversit`
a CaFoscari di Venezia. La conoscenza del
programma pu` u essere approfondita utilizzando un qualsiasi manuale di Maple.

INDICE DEI PARAGRAFI

1. Calcoli, espressioni e funzioni.

2. Risoluzione di equazioni e sistemi.

3. Limiti, derivate, integrali.

4. Funzioni di pi`
u variabili e grafici.

5. Algebra delle matrici.

6. Introduzione alla programmazione.

1 1. Calcoli, espressioni e funzioni


1.1 Calcoli numerici e letterali

Maple `e in grado di soddisfare esigenze di calcolo sia di tipo simbolico che


numerico.
1.1.1 Numeri razionali e numeri floating point

Provate a calcolare una somma algebrica di due numeri interi. Seguite


lesempio e battete il tasto di ritorno a capo.
> 3-5;
2
NB: non `e necessario scrivere = mentre `e obbligatorio concludere
lespressione con ;
> 7/2;

7
2
NB: non viene eseguita la divisione in modo numerico per non perdere
precisione negli eventuali calcoli successivi. Per Maple, 7/2 e 3.5 sono oggetti
diversi: il primo `e un numero razionale, il secondo `e un numero in virgola
mobile (floating point). Per chiarire la differenza consideriamo uno stesso
calcolo eseguito con Maple utilizzando la notazione razionale e con virgola:
> (1/3.0)*3;
.9999999999
> (1/3)*3;
1
NB: il simbolo * indica la moltiplicazione e non pu`
u essere sottinteso.
Si noti che il primo calcolo viene effettuato in virgola mobile anche se un solo
numero (3.0) `e di tipo floating point. Il secondo calcolo `e esatto perch`e 1/3 `e
riconosciuto e trattato come numero razionale. Vediamo che pasticci possono
accadere: consideriamo un calcolo in cui siano utilizzate le due notazioni
appena viste
> (1/3.0)*3-(1/3)*3;

.1 109
cio`e -0.1 per un miliardesimo ovvero -0.0000000001 mentre, ovviamente,
dovrebbe risultare 0.
Possiamo chiedere un calcolo numerico pi` u accurato chiedendo a Maple di
utilizzare un maggior numero di cifre (digits) decimali:
> Digits:= 10;

Digits := 10
> (1/3.0)*3-(1/3)*3;
.1 1024
ora gli zeri che precedono la cifra 1, dopo la virgola, sono 24: si tratta di un
numero molto vicino allo zero ma non `e esattemente zero.
1.1.2 Arrotondamenti, troncamenti ed errori

La precisione nei calcoli effettuati da Maple `e assai elevata, ma alla precisione


dei calcoli `e necessario accompagnare attenzione nel fornire i dati alla
macchina e nellinterpretare i risultati che la macchina restituisce. Ad esempio
se forniamo dati poco precisi `e inutile, se non dannoso, utilizzare molte cifre
decimali nei calcoli effettuati da Maple. Vediamo allora come comportarci in
alcuni casi frequenti.
Anzitutto, quando `e opportuno trascurare alcune cifre decimali di un numero
possiamo semplicemente tenere solo le cifre che ci interessano: effettuiamo in
tal caso un troncamento del numero.
Possiamo diminuire lerrore nel considerare il dato effettuando un
arrotondamento. Effettuare un arrotondamento significa aumentare di una
unit`
a lultima cifra che consideriamo qualora la prima cifra che stiamo per
eliminare sia maggiore o uguale a 5, troncare il numero altrimenti.
Ad esempio se
> x:=123.4492;
x := 123.4492
volendo considerare due cifre decimali con un troncamento otteniamo il
numero 123.44, arrotondando troviamo invece 123.45. Se desideriamo una sola
cifra decimale allora sia troncando che arrotondando otteniamo 123.4.
E chiaro che in generale larrotondamento, a parit`
a di cifre considerate,
consente di ridurre lerrore commesso ed `e pertanto preferibile.
Vediamo ora cosa accade se effettuiamo gli arrotondamenti troppo presto.
Supponiamo di dover calcolare quanto vino sia necessario per riempire un
contenitore cilindrico di alluminio (qui semplifichiamo e supponiamo si tratti
di un cilindro perfetto). Prendiamo le misure interne del cilindro. Con un
calibro (precisione 1/10=0.1 mm) riusciamo a misurare il diametro:
> Diam:= 9.31 ; # cm

Diam := 9.31
per laltezza usiamo un metro con precisione di un millimetro:
> Altezza:= 19.4 ; # cm

Altezza := 19.4
Calcoliamo il volume:
> Volume:=(Diam/2)^2*Pi*Altezza; # il risultato e
` in cm^3
Volume := 420.3790850
> evalf(%);
1320.659845
AnzichE ` considerare lintera cifra decidiamo di considerare solo le quattro cifre
a sinistra della virgola.

Quindi, arrotondando allunit` a, otteniamo 1321 centimetri cubi (in litri:


1,321). Supponiamo che il vino costi 0,51 euro al litro e di dover riempire
19800 lattine. Il costo che dovremo sostenere sar`
a allora:
> Costo_totale:=1.321*0.51*19800;

Costo totale := 13339.45800

ovvero 13339,46 euro.

E una bella cifra che ci spinge ad effettuare una valutazione pi`


u precisa.
Tornando al calcolo del volume prendiamo subito qualche cifra in pi` u, anzi
teniamo tutte quelle che vediamo scritte, non ci costa pi`u fatica:
> Costo_totale:=1.320659845*0.51*19800;

Costo totale := 13336.02312

La differenza, in euro, `e data da


> 13339.46-13336.02;
3.44

Lesempio ci suggerisce di effettuare i calcoli ritardando il pi`


u possibile il
momento nel quale effettuare gli arrotondamenti.

Errori nei dati iniziali e trasmissione dellerrore

Ma il nostro conto `e anche affetto da un altro errore, un errore inevitabile


anche se meno evidente, dovuto alla precisione con la quale sono noti i dati
iniziali.

Per misurare il diametro del cilindro avevamo infatti a disposizione un calibro


con precisione di un decimo di millimetro. In realt` a dunque siamo certi che il
diametro (Diam=9,31 cm) ha una misura compresa tra 9,30 e 9,32 cm; di pi` u
non possiamo chiedere al calibro. Diciamo che lerrore assoluto in questa
misura `e di 0,01 cm e possiamo scrivere Diam = 9,310,01. Lerrore percentuale,
o errore relativo, `e dato dal rapporto tra lerrore assoluto e la misura effettuata
> er_Diam:=0.01/9.32;

er Diam := .001072961373

vale a dire circa uno su mille.

Analogamente per laltezza, lerrore assoluto `e di 0,1 cm, ovvero Altezza=19,4


0,1 cm. Lerrore relativo `e in tal caso:
> er_Altezza:=0.1/19.4;
er Altezza := .005154639175

quindi dellordine del 5 per mille.

Ma quale errore commettiamo nel calcolo del volume?

Si dimostra che moltiplicando tra loro due misure lerrore percentuale


trasmesso nel calcolo `e dato dalla somma degli errori percentuali. Nel nostro
caso allora:
> er_Volume:=er_Diam+er_Diam+er_Altezza;

er Volume := .007300561921

Lerrore relativo nel calcolo del volume `e dunque del 7 per mille (perchE `
sommiamo due volte lerrore relativo del diametro?). Lo stesso errore relativo
si ripercuote sul calcolo del costo totale. Si noti che gli altri fattori che
compaiono nel calcolo del costo totale sono il numero 1/2, che `e esatto cio`e con
errore assoluto nullo, e , che Maple tiene in memoria con un numero di cifre
significative sufficientemente elevato da poter essere considerato con errore
relativo trascurabile.

In termini assoluti il calcolo del volume `e affetto allora dallerrore:


> ea_Volume:=er_Volume*Volume;

ea Volume := 3.069003540

> evalf(%);
9.641558976

In realt`
a quindi il volume di una singola lattina `e 1320.659845 9.641558976
ovvero di millilitri 132110. Lerrore su di una singola lattina `e dellordine di
mezzo cucchiaio da cucina!

Per quanto riguarda il costo complessivo abbiamo invece:


> ea_Costo_totale:=er_Volume*Costo_totale;

ea Costo totale := 97.36046257

quindi un errore dellordine di un centinaio di euro, un errore che rende in


realt`
a trascurabile, in questo caso, lerrore complessivo dovuto al precedente
arrotondamento al centimetro cubo del volume della lattina!

Problemi simili a quelli incontrati nel caso di una moltiplicazione si hanno


anche nella trsmissione degli errori effettuando altre operazioni tra i dati: per
un loro adeguato trattamento rimandiamo ai testi specializzati in analisi
numerica.
1.1.3 Calcoli simbolici

Maple `e in grado di fare calcoli di tipo letterale utilizzando moltissimi comandi


per la manipolazione algebrica. Vediamo qualche esempio.
> 3*a-5*a+4*a-b*a;

2aba

Manipoliamo lespressione raccogliendone i fattori:


> factor(%);

a (2 + b)

NB: per indicare la riga di calcolo (execution group) appena eseguita si utilizza
il simbolo di percentuale (%), nelle versioni di Maple meno recenti lo stesso
effetto si ha utilizzando il doppio apice ().
> 3*x*(x^2-y^2)^2/((x+y)*9*x);

1 (x2 y2 )2
3 x+y
NB: lelevamento a potenza viene indicato dal simbolo .

Si pu`u notare che Maple effettua immediatamente le semplificazioni ovvie. Ma


pu`u fare di meglio:
> simplify(%);

1
(x y) (x2 y2 )
3
Vediamo qualche altra semplificazione:
> root(x^2,2);

x2
> simplify(%);

csgn(x) x

NB: csgn(x) indica il segno di x. Poteva far di meglio scrivendo il valore


assoluto di x, che pure `e definito (si provi a scrivere >abs(x);) e si legge
meglio: questa `e una avvisaglia del fatto che Maple pu` u perdersi in un bicchier
dacqua.

Ancora un esempio:
> (x+2)*(x^2-1)/(x+1);

(x + 2) (x2 1)
x+1
cerchiamo di riscrivere lespressione in modo pi`
u semplice:
> factor(%);
(x 1) (x + 2)

Proviamo ad eseguire le operazioni


> expand(%);

x2 + x 2

ancora non ci soddisfa, torniamo a fattorizzare


> factor(%);

(x 1) (x + 2)

Rifacciamo il conto in ordine diverso


> (x+2)*(x^2-1)/(x+1);

(x + 2) (x2 1)
x+1
proviamo prima ad espandere
> expand(%);

x3 x 2 x2 2
+
x+1 x+1 x+1 x+1
un disastro! Proviamo a vedere se si semplifica qualcosa
> simplify(%);

x2 + x 2

meglio. Ora proviamo a fattorizzare


> factor(%);

(x 1) (x + 2)

Lordine delle operazioni `e ovviamente importante: labbiamo provato tante


volte facendo i conti a mano, qui almeno possiamo riprovare velocemente.
Provate a rifare il conto cambiando ancora lordine delle manipolazioni e con
altre espressioni.

Dagli esempi fin qui visti simplify pu` u apparire come il comando pi`
u utile; in
realt`
a il comando pi`
u flessibile `e expand che consente, ad esempio, di stabilire
quale fattore raccogliere:
> expand((x+2)*(x+3)*(y+z),x);

x2 y + x 2 z + 5 x y + 5 x z + 6 y + 6 z
> expand((x+2)*(x+3)*(y+z),x+2);
(x + 2) x y + (x + 2) x z + 3 (x + 2) y + 3 (x + 2) z
> expand((x+2)*(x+3)*(y+z),y+z);
(y + z) x2 + 5 (y + z) x + 6 y + 6 z
> factor(%);
(x + 2) (x + 3) (y + z)

1.1.4 Altre informazioni

Maple consente operazioni sui numeri interi quali la divisione con resto, il
fattoriale, la fattorizzazione..., sui numeri complessi, su insiemi, vettori,
matrici,...

Sono inoltre definite alcune costanti quali


> exp(1);

e
> Pi;

1.2 Assegnazioni e funzioni

Possiamo associare un nome ad un oggetto matematico quale ad esempio


unespressione, unequazione, una funzione. La sintassi `e nome := oggetto; .
Ad esempio
> fattore1:=x*y;

fattore1 := x y

ora fattore1 `e una variabile che vale xy. Consideriamo una seconda variabile
> fattore2:=x*z;

fattore2 := x z

e moltiplichiamo
> prodotto:=fattore1*fattore2;

prodotto := x2 y z

Maple ha gi`a effettuato qualche conto riconoscendo il valore delle variabili


utilizzate.

Possiamo definire in questo modo anche le funzioni:


> f:=x->x^2-1;

f := x x2 1

La variabile f `e in questo caso un oggetto di tipo funzione che possiamo


utilizzare come siamo abituati, per esempio per valutarla in un punto
> f(2);
3
ma anche in un punto simbolico
> f(antonio);

antonio 2 1
o componendola
> f(y-1);

(y 1)2 1
Combiniamo una variabile di tipo numero con la funzione f
> alfredo:=3;

alfredo := 3
> f(alfredo);
8
E poi semplicissimo disegnare grafici mediante il comando plot:
> plot(f,-2..4,-2..5);

2 1 0 1 2 3 4
1

Nellesempio la porzione di grafico che interessa `e quella racchiusa nel


rettangolo [-2,4]x[-2,5]. Il secondo argomento del comando plot `e un intervallo
contenuto nel dominio di f relativamente al quale interessa rappresentare il
grafico di f. Il terzo argomento `e opzionale e, se presente, individua lintervallo
di interesse relativamente al codominio.
2 2. Risoluzione di equazioni e sistemi

2.1 Equazioni

La risoluzione di equazioni `e particolarmente semplice, il comando da


utilizzare `e solve.
> solve({x^2=4},{x});

{x = 2}, {x = 2}

Maple commette errori nel caso di calcoli letterali, anche semplici, se ci sono
parametri
> solve({a*x+b=0},{x});

b
{x = }
a
(cosa succede se a=0?) e non risponde in alcuni casi numerici proibiti
> solve({0*x+3=0},{x});

E capace di lavorare con i numeri complessi


> solve({x^2+1=0},{x});

{x = I}, {x = I}

(I `e lunit`
a immaginaria vale a dire il numero complesso tale che I2=-1).

Vediamo qualche altro esempio


> solve({x^3+x^2-5*x=0},{x});

1 1 1 1
{x = 0}, {x = + 21}, {x = 21}
2 2 2 2
> solve({x^3-13*x+12=0},{x});

{x = 1}, {x = 3}, {x = 4}
> solve({x^2+y=0},{x,y});
{y = x2, x = x}
> solve({x^2+y^2=0},{x,y});
{x = I y, y = y}, {x = I y, y = y}
> solve({x^7+x^2=0},{x});
1 1 1 p
{x = 0}, {x = 0}, {x = 1}, {x = 5 + I 2 5 + 5},
4 4 4
1 1 1 p 1 1 1 p
{x = + 5 I 2 5 5}, {x = + 5 + I 2 5 5},
4 4 4 4 4 4
1 1 1 p
{x = 5 + + I 2 5 + 5}
4 4 4
> solve({exp(x)*x^2-3=0},{x});
1 1
{x = 2 LambertW( 3)}, {x = 2 LambertW( 3)}
2 2
Nellultimo esempio LambertW `e una funzione che soddisfa lequazione
LambertW(x) * exp(LambertW(x)) = x .

Maple `e riuscito a fornirci una soluzione esatta anche in questo caso.

In genere siamo per`


u pi`u interessati alla risoluzione numerica di una equazione
come la precedente. Il comando da usare `e in tal caso fsolve, con la stessa
sintassi di solve
> fsolve({exp(x)*x^2-3 = 0},{x});

{x = 1.033230904}

Ecco un altro caso interessante


> f:=sin(x);

f := sin(x)
> sol1:=solve({f=0.3},{x});
sol1 := {x = .3046926540}
> sol2:=fsolve({f=0.3},{x});
sol2 := {x = .3046926540}

Quale soluzione `e corretta? In realt`a queste sono solo due delle infinite
soluzioni dellequazione considerata. Maple non `e in grado, in questo caso, di
avvisarci della presenza di altre soluzioni.

Possiamo comunque accertare la bont` a delle soluzioni trovate sostituendole


come argomento della funzione f utilizzando il comando subs
> subs(sol1,f);

sin(.3046926540)

chiedendo il calcolo del valore della funzione nel punto mediante il comando
evalf
> evalf(%);
.3000000000
> subs(sol2,f);

sin(.3046926540)
> evalf(%);

.3000000000
2.2 Sistemi di equazioni

Per risolvere sistemi di equazioni `e sufficiente scrivere come argomenti del


comando solve lelenco delle equazioni e delle variabili rispetto alle quali
risolverle
> eq1:=3*x+2*y=2;

eq1 := 3 x + 2 y = 2
> eq2:=x-y=4;

eq2 := x y = 4
> solve({eq1,eq2},{x,y});

{x = 2, y = 2}
Vediamo un caso in cui il sistema presenta infinite soluzioni
> eq3:=x+2*y=1;

eq3 := x + 2 y = 1
> eq4:=2*x+4*y=2;

eq4 := 2 x + 4 y = 2
> solve({eq3,eq4},{x,y});

{y = y, x = 2 y + 1}
Mettiamo ora alla prova Maple su di un sistema di due equazioni non lineari.
Sia
> primo1:=3*x^3-exp(y);
primo1 := 3 x3 ey
il primo membro della prima equazione e
> primo2:=y^2+x;

primo2 := y2 + x
il primo membro della seconda equazione e risolviamo il sistema primo1=0,
primo2=3 dando anche un nome allinsieme delle soluzioni
> soll:=fsolve({primo1=0,primo2=3},{x,y});

soll := {x = .4052948807, y = 1.610808840}


Controlliamo lesattezza del risultato sostituendo le soluzioni trovate in primo1
e primo2
> subs(soll,primo1);

.1997260023 e(1.610808840)
> evalf(%);
0.
> subs(soll,primo2);
3.000000000
Si noti che la soluzione trovata non `e unica (anche se Maple non lo dice):
> subs({x=1.098015136,y=1.379124673},primo1);

3.971423811 e1.379124673
> evalf(%);
0.
> subs({x=1.098015136,y=1.379124673},primo2);
3.000000000

3 3. Limiti, derivate, integrali

Maple fornisce tutti gli strumenti tradizionali dellanalisi. Iniziamo a vedere


alcune delle possibilit`
a offerte nel caso di funzioni reali di variabile reale.
Arriveremo a poter svolgere il tradizionale studio di funzione in modo
completo.

3.1 3.1 Limiti

Definiamo una funzione della quale andremo poi a cercare alcuni limiti
> g:= x-> (x+1)*(x+2)*(x-3)/(x-1);

(x + 1) (x + 2) (x 3)
g := x
x1
Proviamo a calcolare il limite per x - > 1. Prima definiamo il limite che ci
interessa

> Limit(g(x),x=1);
(x + 1) (x + 2) (x 3)
lim
x1 x1
e adesso cerchiamone il valore
> value(%);

undefined
La risposta `e corretta infatti calcolando i limiti da sinistra e da destra troviamo
> Limit(g(x),x=1,left);

(x + 1) (x + 2) (x 3)
lim
x1 x1
> value(%);

Per il limite destro utilizziamo la lettera minuscola nel comando limit , questo
consente di ottenere subito il valore numerico del limite
> limit(g(x),x=1,right);

Se gli ultimi due limiti calcolati da Maple sono giusti (e lo sono) allora il primo
limite cercato non esiste. Vediamo come si calcolano i limiti a + e - infinito.
Ad esempio
> Limit(g(x),x=-infinity);

(x + 1) (x + 2) (x 3)
lim
x() x1
> value(%);

3.2 3.2 Derivate

Consideriamo una funzione di x e contenente il parametro k:


> f:=x->x*cos(k*x);

f := x x cos(k x)
> diff(f(x),x);

cos(k x) x sin(k x) k

In realt`
a il fatto che f sia definita come funzione di x a Maple interessa poco.
Possiamo infatti derivare anche rispetto a k:
> diff(f(x),k);

x2 sin(k x)

Cerchiamo ora i punti stazionari di una funzione. Definiamo la funzione


> h:=x->x^3-2*x^2-4*x;

h := x x3 2 x2 4 x

e calcoliamone i punti stazionari ai quali diamo anche un nome (staz ):


> staz:=solve(diff(h(x),x)=0,x);

2
staz := 2,
3
Pi`u in generale possiamo studiare la monotonia della funzione determinando
gli intervalli nei quali la derivata si mantiene non negativa:
> solve(diff(h(x),x)>=0,x);

2
RealRange(, ), RealRange(2, )
3
Otteniamo cos` che -2/3 `e un punto di massimo locale mentre `e di minimo
locale il punto 2.
Vediamo come classificare i punti stazionari utilizzando la derivata seconda.
Anzitutto calcoliamola nel generico punto x:
> diff(h(x),x,x);
6x4
Speghiamo ora a Maple di considerare lespressione appena trovata come
immagine di x tramite la funzione derivata seconda di h, che chiameremo
DDh; per far questo usiamo il comando unapply
> DDh:=unapply(%,x);

DDh := x 6 x 4
Adesso possiamo valutare la derivata seconda nei due punti stazionari. Nel
primo punto si ha
> DDh(staz[1]);

8
perci`
u si tratta di un massimo. Nel secondo punto stazionario si ha
> DDh(staz[2]);
8
che ci conferma che il punto 2 `e di minimo per h. Vediamo il grafico
(numerico) di h fornito da Maple:
> plot(h(x),x=-3..5,-10..10);

10
8
6
4
2

3 2 1 0 1 2 3 4 5
2 x
4
6
8
10
3.3 3.3 Uno studio di funzione

Esaminiamo le caratteristiche del grafico di una funzione in modo dettagliato.


Consideriamo la funzione
> f:=x->x^3*(x+1)/(x^2+2);

x3 (x + 1)
f := x
x2 + 2
Proviamo a farci disegnare il grafico da Maple:
> plot(f(x),x=-10..10);

100

80

60

40

20

10 8 6 4 2 0 2 4 6 8 10
x

Pare che in 0 ci sia un minimo. Ma vediamo di effettuare uno studio delle


qualit`
a delle propriet`
a della funzione in modo completo. Partiamo con il
calcolo dei limiti:
> limit(f(x),x=-infinity);


> limit(f(x),x=+infinity);

Studiamo il segno di f:
> solve(f(x)>=0,x);

RealRange(, 1), RealRange(0, )

pertanto f `e negativa tra -1 e 0, positiva altrove. Per studiare la monotonia


calcoliamo la derivata di f
> diff(f(x),x);
x2 (x + 1) x3 2 x4 (x + 1)
3 2
+ 2
x +2 x +2 (x2 + 2)2

che si pu`
u semplificare un po:
> simplify(%);

x2 (2 x3 + 8 x + x2 + 6)
(x2 + 2)2

Cerchiamo i punti stazionari


> staz:=solve(diff(f(x),x)=0,x);

47
1 (1/3) 6 1
staz := 0, 0, %1 + (1/3)
,
6 %1 6
1 (1/3) 47 1 1 1 1 (1/3) 47 1
%1 + I 3 ( %1 ),
12 12 %1(1/3) 6 2 6 6 %1(1/3)
1 (1/3) 47 1 1 1 1 (1/3) 47 1
%1 I 3 ( %1 )
12 12 %1(1/3) 6 2 6 6 %1(1/3)

%1 := 253 + 18 518
Si leggono proprio male! Prima di tentare di scrivere meglio i punti stazionari
vediamo cosa si pu`u dire riguardo alla monotonia fornendo a Maple solo il
fattore che determina il segno della derivata
> solve(2*x^3+8*x+x^2+6>=0,x);

47
1 6 1
RealRange (253 + 18 518)(1/3) + ,
6 (253 + 18 518)(1/3) 6

ancora una volta qualcosa di poco leggibile. Proviamo a riscrivere i punti


stazionari:
> s1:=evalf(staz[1]);

s1 := 0.
> s2:=evalf(staz[2]);
s2 := 0.
> s3:=evalf(staz[3]*1.);
s3 := .7212304534
> s4:=evalf(staz[4]);
s4 := .1106152263 2.036497585 I
> s5:=evalf(staz[5]);
s5 := .1106152263 + 2.036497585 I
Valutiamo f nel terzo punto stazionario:
> f(s3);

.04149894724

Proviamo ora ad utilizzare la derivata seconda per classificare i punti stazionari


> DDf:=unapply(diff(f(x),x,x),x);

x (x + 1) 6 x2 14 x3 (x + 1) 4 x4 8 x5 (x + 1)
DDf := x 6 2
+ 2 2 2
2 2
+
x +2 x +2 (x + 2) (x + 2) (x2 + 2)3

Nei punti stazionari si ottiene:


> evalf(DDf(staz[1]));
0.
> evalf(DDf(staz[3]));
.7926818053

Il punto terzo punto stazionario `e pertanto di minimo locale. Per classificare il


primo punto stazionario abbiamo bisogno di calcolare la derivata terza:
> DDDf:=unapply(diff(f(x),x,x,x),x);

x+1 18 x 54 x2 (x + 1) 42 x3 96 x4 (x + 1) 24 x5
DDDf := x 6 + + +
x2 + 2 x2 + 2 (x2 + 2)2 (x2 + 2)2 (x2 + 2)3 (x2 + 2)3
48 x6 (x + 1)

(x2 + 2)4
> evalf(DDDf(staz[1]));

3.

Lorigine `e dunque un punto di flesso.

Avendo capito che i punti stazionari sono certamente compresi nellintervallo


[-1, 1], proviamo a tracciare un secondo grafico numerico di f, questa volta
restringendo il range da considerare
> plot(f(x),x=-1.2..1);
0.6

0.5

0.4

0.3

0.2

0.1

1 0.5 0 0.5 1
x

Lo studio di funzione consente di guidare il modo di tracciare anche il grafico


numerico molto meglio rispetto al fuorviante grafico numerico tracciato
allinizio.

3.4 3.4 Integrali

Possiamo calcolare sia integrali indefiniti che definiti. Ad esempio, calcoliamo


una primitiva della funzione
> f:=x->x*exp(x+1);

f := x x e(x+1)

usando il comando int:


> int(f(x),x);

e(x+1) (x + 1) 2 e(x+1)

Verifichiamo i calcoli derivando


> diff(%,x);

e(x+1) (x + 1) e(x+1)

e semplificando
> simplify(%);

x e(x+1)
ottenendo la conferma della correttezza del calcolo dellintegrale.

Nota: anche se non sappiamo se il programma ha fornito una primitiva


corretta ci possiamo senzaltro fidare delle derivate fornite da Maple. Si tratta
di un conto puramente meccanico che un programmatore pu` u insegnare ad un
elaboratore con poche righe di istruzioni in un qualsiasi linguaggio di
programmazione.

Per calcolare un integrale definito `e sufficiente indicare, oltre alla variabile,


lintervallo di integrazione
> Int(f(x),x=0..2);
Z 2
x e(x+1) dx
0
> value(%);
e3 + e

Consideriamo ora una classico esempio di funzione le cui primitive non


possono essere scritte a partire da funzioni elementari utilizzando operazioni
algebriche o composizione di funzioni:
> g:=x->exp(-x^2);
2
g := x e(x )

calcoliamone lintegrale generalizzato nellintervallo tra 0 e pi`


u infinito
> int(g(x),x=0..+infinity);

1

2
che `e corretto. Se vogliamo calcolare lo stesso integrale tra 0 e 1, ad esempio,
Maple ovviamente non pu` u far molto:
> int(g(x),x=0..5);

1
erf(5)
2
dove erf ( x ) = 2/sqrt(Pi) * int ((exp(-x2), t = 0..x ). Quindi Maple si mangia
la coda, e non poteva che

essere cos`. Possiamo per`


u chiedere una valutazione numerica dellintegrale:
> evalf(value(%));
.8862269255
4 4. Funzioni di pi`
u variabili e grafici

4.1 4.1 Limiti e derivate

Vediamo molto velocemente come quanto visto per le funzioni di una sola
variabile reale si estenda al caso di due variabili; lestensione a pi`
u variabili
risulter`
a poi del tutto ovvia. Cominciamo definendo una funzione nelle
variabili x e y:
> f:=(x,y)->x^2*y-3*y/x;

3y
f := (x, y) x2 y
x
Proviamo a calcolare due limiti (facili)
> limit(f(x,y),{x=2,y=3});

15
2
> limit(f(x,y),{x=0,y=3});
undefined
Se tentiamo con altre funzioni facciamo presto a mettere in difficolt`
a Maple.
La funzione
> g:=(x,y)->x^2*y^2/(x^2*y^2+(x-y)^2);

x2 y 2
g := (x, y)
x2 y 2 + (x y)2
non ha limite in (0,0), Maple non risponde:
> limit(g(x,y),{x=0,y=0});

x2 y 2
limit( , {x = 0, y = 0})
x2 y2 + (x y)2
Ma anche nel caso di una funzione con limite 0 in (0,0) Maple si arena
> limit(x^3/(x^2+y^2),{x=0,y=0});

x3
limit( , {x = 0, y = 0})
x2 + y 2
Non ci sono ovviamente problemi nel calcolo delle derivate parziali:
> diff(g(x,y),x);

x y2 x2 y2 (2 x y2 + 2 x 2 y)
2
x2 y 2
+ (x y) 2 (x2 y2 + (x y)2 )2
> simplify(diff(g(x,y),y));
x3 y (x y)
2
(x2 y2 + x2 2 x y + y2 )2
Ed ecco una derivata seconda mista
> simplify(diff(g(x,y),x,y));

x2 y2 (6 x y 3 x2 + x2 y2 3 y2 )
2
(x2 y2 + x2 2 x y + y2 )3

Per valutare in un punto la derivata parziale seconda appena calcolata


definiamo la funzione
> DDXY:=unapply(%,(x,y));

x2 y2 (6 x y 3 x2 + x2 y2 3 y2 )
DDXY := (x, y) 2
(x2 y2 + x2 2 x y + y2 )3

che ora possiamo valutare dove ci interessa, ad esempio in (1,-1):


> DDXY(1,-1);

22
125

4.2 4.2 Grafici

Le possibilit`
a grafiche sono uno dei punti forti dei programmi tipo Maple.
Analizziamo prima alcune possibilit` a non ancora esplorate riguardo alle
funzioni di una sola variabile. Passeremo poi alle funzioni di due variabili.

4.2.1 4.2.1 Alcune potenzialit`


a grafiche per funzioni di una sola vari-
abile

> plot(sin(x),x=0..2*Pi,title="funzione seno");


funzione seno
1

0.5

0 1 2 3 4 5 6
x

0.5

Possiamo anche tentare una compressione dellasse delle x per avere unidea
del comportamento della funzione per valori molto grandi dellargomento
> plot(sin(x),x=0..infinity);

0 infinity
x

Ma attenzione allinterpretazione delle propriet`


a geometriche del grafico.
Guardate cosa accade del grafico della funzione logaritmo in base e (che `e una
funzione concava!):
> plot(ln(x),x=0..infinity);
infinity

0 infinity
x

-infinity

Per utilizzare potenzialit`


a grafiche disponibili solo a domanda, chiediamo a
Maple di caricare il modulo plots:
> with(plots);

Warning, the name changecoords has been redefined

[animate, animate3d , animatecurve, arrow, changecoords, complexplot, complexplot3d ,


conformal, conformal3d, contourplot, contourplot3d , coordplot, coordplot3d ,
cylinderplot, densityplot, display, display3d , fieldplot, fieldplot3d, gradplot,
gradplot3d , implicitplot, implicitplot3d, inequal , listcontplot, listcontplot3d,
listdensityplot, listplot, listplot3d, loglogplot, logplot, matrixplot, odeplot , pareto,
pointplot, pointplot3d, polarplot, polygonplot, polygonplot3d ,
polyhedra supported, polyhedraplot, replot, rootlocus, semilogplot, setoptions,
setoptions3d , spacecurve, sparsematrixplot, sphereplot, surfdata, textplot,
textplot3d , tubeplot]

Possiamo ora utilizzare tutti i comandi elencati sopra. Per esempio possiamo
utilizzare le coordinate polari
> polarplot(1,theta=0..2*Pi);
1

0.5

1 0.5 0.5 1

0.5

Per un confronto tra coordinate cartesiane e polari prendiamo la curva di


equazioni parametriche x=t, y=t in coordinate cartesiane
> plot([t,t,t=-2*Pi..2*Pi]);

6 4 2 0 2 4 6
2

e in coordinate polari, vale a dire interpretando la prima coordinata come la


distanza dallorigine e la seconda coordinata come angolo rispetto al semiasse
positivo delle ascisse
> polarplot([t,t,t=-2*Pi..2*Pi]);
1
6 4 2 2 4 6
0
1

Veniamo ora ad un grafico in scala semilogaritmica


> logplot(10^x,x=0..10);

1e+10
1e+09
1e+08
1e+07
1e+06
1e+05
.1e5
.1e4
.1e3
.1e2
1. 2 4 6 8 10
x

e ad una curva definita mediante una equazione ben nota


> implicitplot(x^2+y^2=1,x=-1..1,y=-1..1);
1

y 0.5

1 0.5 0 0.5 1
x

0.5

Questultimo comando `e particolarmente utile quando si hanno curve meno


note che Maple traccia

senza protestare
> implicitplot(exp(x^2*y)-exp(y)=sin(4*x),x=-2..2,y=-5..5);

y
2

1.5 1 0.5 0 0.5 1 1.5 2


x
2

4
4.2.2 4.2.2 Grafici per funzioni di due variabili

Vediamo alcuni esempi di grafici in tre dimensioni ottenuti con il comando


plot3d e come tracciare le curve di livello.
> plot3d(x^2+y^2,x=-4..4,y=-4..4,style=patch,color=x,grid=[50,50],orien
> tation=[160,100],axes=boxed,title=paraboloide);

paraboloide

30
25
20
15
10
5
4 2 0
2 y 2 4
0 0
4 2 x

> contourplot(x^2+y^2,x=-5..5,y=-5..5,contours=25);

y
2

4 2 0 2 4
x
2

4
> plot3d(y^2-x^2,x=-4..4,y=-4..4,style=contour,contours=50,grid=[50,50]
> ,orientation=[200,60],color=black,axes=boxed,title=sella);

sella

15
10
5
0
5 4
10 2
15 0 x
4 2
2 0
y 2 4
4

> densityplot(x^2+y^2,x=-5..5,y=-5..5);

4
y
2

4 2 0 2 4
x
2

4
5 5. Algebra delle matrici

Esaminiamo ora alcune delle possibilit`a che Maple offre nel calcolo matriciale.
Anzitutto vi sono due pacchetti che possiamo richiamare per operare sulle
matrici e, pi`
u in generale, su probelmi di algebra lineare: linalg eLinearAlgebra .
Qui esamineremo solo alcune delle possibilit` a offerte dal primo che andiamo a
caricare:
> with(linalg);

Warning, the protected names norm and trace have been redefined and
unprotected

[BlockDiagonal , GramSchmidt, JordanBlock , LUdecomp, QRdecomp, Wronskian, addcol,


addrow, adj , adjoint, angle, augment , backsub, band , basis, bezout , blockmatrix,
charmat, charpoly, cholesky, col, coldim, colspace, colspan, companion, concat,
cond , copyinto, crossprod, curl, definite, delcols, delrows, det, diag, diverge,
dotprod, eigenvals, eigenvalues, eigenvectors, eigenvects, entermatrix, equal,
exponential , extend , ffgausselim, fibonacci , forwardsub, frobenius, gausselim,
gaussjord, geneqns, genmatrix , grad, hadamard , hermite, hessian, hilbert,
htranspose, ihermite, indexfunc, innerprod, intbasis, inverse, ismith, issimilar,
iszero, jacobian, jordan, kernel, laplacian, leastsqrs, linsolve, matadd , matrix ,
minor, minpoly, mulcol, mulrow, multiply, norm, normalize, nullspace, orthog,
permanent, pivot, potential, randmatrix , randvector , rank , ratform, row, rowdim,
rowspace, rowspan, rref , scalarmul, singularvals, smith, stackmatrix, submatrix ,
subvector, sumbasis, swapcol, swaprow, sylvester, toeplitz, trace, transpose,
vandermonde, vecpotent, vectdim, vector, wronskian]

Definiamo anzitutto due vettori di 3 componenti:

> v:= vector(3,[1,2,3]);w:=vector(3,[5,6,7]);


v := [1, 2, 3]
w := [5, 6, 7]

Possiamo ora effettuare tutte le operazioni tra vettori.

Partiamo con la somma:


> v+w;

v+w

Per vedere esplicitamente il risultato dobbiamo valutare lespressione con


listruzione evalm:
> evalm(%);
[6, 8, 10]

Ecco invece la moltiplicazione per uno scalare


> evalm(3*w);

[15, 18, 21]

Il prodotto scalare, o prodotto interno, si scrive invece


> innerprod(v,w);

38

Passiamo alle matrici. Definiamo una matrice 2 per 3 e chiamiamola A:

> A := matrix( 2, 3, [[1,3,2], [-5,14,9]]);


 
1 3 2
A :=
5 14 9

una matrice 3 per 3 di nome B:

> B := matrix( 3, 3, [[1,-1,1], [0,20,-8], [2,0,2]]);



1 1 1
B := 0 20 8
2 0 2

e una seconda matrice 2 per 3 di nome C:


> C := matrix( 2, 3, [[0,5,2], [1,2,-1]]);
 
0 5 2
C :=
1 2 1

e facciamo un po di operazioni tra matrici:

> evalm(A+C);
 
1 8 4
4 16 8
> evalm(2*A);
 
2 6 4
10 28 18

Per loperazione di moltiplicazione tra matrici (righe per colonne) dobbiamo


usare il simbolo &* :
> evalm(A&*B);
 
5 59 19
13 285 99

La trasposta e linversa richiedono solo lutilizzo dei corrispondenti termini


inglesi:
> transpose(A);

1 5
3 14
2 9

> BINV:=inverse(B);
5 1 3
2 8 4

1
BINV := 1 0
2

5 1 5
2 8 4
Ha fatto bene i conti? Controlliamo:
> evalm(B&*BINV);

1 0 0
0 1 0
0 0 1

OK!

Ancora, possiamo calcolare determinante e rango:


> det(B);
16
> rank(A);
2

Naturalmente ci vengono segnalati gli errori nellimpostare i calcoli. Ad


esempio non `e possibile moltiplicare B per A:
> evalm(B&*A);

Error, (in linalg[multiply]) non matching dimensions for vector/matrix


product

Data la matrice A ed il vettore dei termini noti


> b:= vector(2,[1,2]);

b := [1, 2]

il sistema Ax=b si risolve con listruzione linsolve:


> x:=linsolve(A,b);
 
5 1 7 29
x := + t 1 , t 1, t1
19 19 19 19
(in questo caso i vettori soluzione sono infiniti e si ottengono al variare di t1
nellinsieme dei numeri reali).

Possiamo ottenere il valore della prima componente del vettore soluzione


> x[1];

5 1
+ t1
19 19
che in corrispondenza di un fissato valore del parametro
> _t[1]:=1;
t 1 := 1

diviene
> x[1];
6
19
Vediamo ora come ottenere la matrice inversa della matrice B in base alla
definizione: linversa, se esiste, risolve lequazione tra matrici BX=I dove I `e la
matrice identit`a. Definiamo la matrice identit` a come una matrice diagonale :
> ID:=diag(1,1,1);

1 0 0
ID := 0 1 0
0 0 1
Quindi risolviamo il sistema

> BINVbis:=linsolve(B,ID);
5 1 3
2 8 4

1
BINVbis := 1 0
2

5 1 5
2 8 4
che `e linversa trovata prima da Maple, possiamo farlo controllare a Maple:
> evalm(BINV-BINVbis);

0 0 0
0 0 0
0 0 0
la loro differenza `e zero quindi coincidono.

6 6. Introduzione alla programmazione

6.1 6.1 Procedure

6.1.1 6.1.1 Introduzione

Spesso nella risoluzione dei problemi accade di dovere eseguire pi` u volte una o
pi`u istruzioni in un ordine stabilito. Si supponga ad esempio di dover calcolare
il montante di una operazione finanziaria oppure un tasso di interesse: per
risolvere diversi problemi del genere cambiano i dati, ma le formule rimangono
sempre le stesse. Sarebbe quindi opportuno evitare di dovere riscrivere le
formule ogni volta, ma memorizzarle una volta per tutte e riutilizzarle quando
servono (risparmiando tempo e fatica). Questa opportunit` a `e offerta dalle
procedure, vediamo come realizzarla.

6.1.2 6.1.2 Un esempio di procedura

Supponiamo di dover calcolare il montante M di un capitale C in regime di


interesse semplice, dopo t anni e con tasso dinteresse annuo i :

M = C*(1 + i*t)

I dati da considerare in ingresso ed in uscita sono, rispettivamente:

dati in ingresso: C (capitale iniziale), t (durata in anni) e i (tasso di


interesse annuo)

dato in uscita: M (montante)

Dichiarazione di un procedura
Per poter riutilizzare pi`
u volte la formula senza avere la necessit`
a di riscriverla
ogni volta, possiamo dichiarare una procedura che esegua la formula del calcolo
del montante comunque vengano specificati i dati in ingresso.

A tale scopo occorre specificare:

un nome da assegnare alla sequenza di calcoli da effettuare (il nome della


procedura)

un avviso per MAPLE che si tratta di una procedura

quali sono i dati in ingresso

come calcolare il risultato

La dichiarazione di una procedura che consenta il calcolo del montante `e:

> montante_IntSempl := proc(C, t, i)


> C*(1+i*t)
> end proc;
montante IntSempl := proc(C, t, i) C (1 + i t) end proc

dove, nellordine, sono specificati:

montante IntSempl: `e il nome che abbiamo scelto per la procedura ed


`e seguito dalloperatore di assegnazione (:=); `e buona regola utilizzare dei
nomi significativi che ci aiutino a ricordare cosa fa la procedura;

proc `e una parola chiave: serve ad avvisare MAPLE che si tratta di una
procedura;

di seguito sono specificati (tra parentesi tonde e separati da virgole) i


dati in ingresso che sono detti parametri (o argomenti) formali della
procedura; nel nostro esempio gli argomenti sono 3: il capitale C, il tempo
t ed il tasso di interesse i. Anche in questo caso la scelta dei nomi e
dellordine degli argomenti `e libera;
la formula che calcola il montante.

Per indicare la fine della dichiarazione della procedura si scrive end oppure
end proc. Se nella dichiarazione non ci sono errori di sintassi, MAPLE
riscrive la procedura (in blu) dopo lend finale.

Esecuzione di una procedura

Una volta dichiarata una procedura, per eseguirla basta scriverne il nome
seguito dai valori che intendiamo assegnare agli argomenti: unistruzione di
questo genere `e detta chiamata della procedura ed i valori passati sono
detti parametri (o argomenti) attuali della chiamata.

Ad esempio, per calcolare il montante corrispondente a C = 1000 euro, t = 10


anni e i = 4% annuo, `e sufficiente scrivere la chiamata avente 1000, 10 e 0.04
come argomenti attuali:
> montante_IntSempl(1000, 10, 0.04);

1400.00

Il valore stampato 1400.00 `e il montante richiesto e viene restituito dalla


procedura perchE` `e il risultato dellultima istruzione eseguita (quella prima
dellend).

Per effettuare unaltra esecuzione, ad esempio con C = 3500 euro , t = 9 anni


e i = 5% annuo, basta scrivere unaltra chiamata:
> montante_IntSempl(3500, 9, 0.05);

5075.00

Alcune raccomandazioni: `e vero che il numero e lordine degli argomenti


formali lo scegliamo noi arbitrariamente, ma una volta fatte, queste scelte
vanno rispettate quando si effettuano le chiamate. Ad esempio, la chiamata:
> montante_IntSempl(9, 3500, 0.05);

1584.00

d`
a un risultato diverso rispetto alla chiamata precedente: giustamente, perchE `
pur trattandosi degli stessi valori, gli argomenti attuali sono scritti in ordine
diverso. Infatti, nella dichiarazione della procedura si era deciso che il primo
argomento fosse il capitale, e perci`u nellultima chiamata viene calcolato il
montante di un capitale di 9 euro dopo 3500 anni al tasso del 5%. Dunque:
lordine degli argomenti attuali deve corrispondere allordine degli argomenti formali.

Vediamo ora cosa accade se togliamo un argomento attuale dalla chiamata:


> montante_IntSempl(1000, 10);

Error, (in montante_IntSempl) montante_IntSempl uses a 3rd argument,


i, which is missing

` nella dichiarazione della procedura gli


`e data una segnalazione derrore perchE
argomenti formali erano 3, mentre in questa chiamata gli argomenti attuali
sono solo 2 (in questo caso MAPLE non sa quanto vale il tasso i); dunque:

il numero degli argomenti attuali deve corrispondere al numero degli argomenti formali.

Una chiamata di procedura restituisce un risultato (lo stesso che viene


stampato) che pu`
u essere assegnato ad una variabile: ad esempio la chiamata
> montante_IntSempl(1200,5,0.03);

1380.00

restituisce il valore 1380 che pu`


u essere assegnato ad una variabile:
> montante := montante_IntSempl(1200,5,0.03);

montante := 1380.00

se quindi scriviamo il nome della variabile `e visualizzato il dato in essa


memorizzato:
> montante;
1380.00

Una procedura pu`


u anche essere priva di argomenti, ad esempio:
> prova := proc()

> print("ciao a tutti")

> end;

prova := proc() print(ciao a tutti) end proc

la procedura ha come unica istruzione una stampa (print) che si limita a


stampare la stringa (= sequenza di simboli alfanumerici) racchiusa tra doppi
apici.
Anche se non ci sono argomenti le parentesi nella chiamata vanno messe:
> prova();

ciao a tutti

6.1.3 6.1.3 Un altro esempio di procedura

Operiamo questa volta di operare in regime di interesse composto, in tal caso,


noti il capitale iniziale C, la durata t dellimpiego ed il tasso dintersse annuo
i, il montante M `e dato da:

M = C*(1 + i)t

Supponiamo in particolare di volere determinare, dati il montante, la durata t


ed il tasso di interesse i, il capitale iniziale e linteresse corrispondenti, ovvero:

C = M / (1 + i)t

I=M-C.

In questo caso i dati del problema sono:

dati in ingresso: M (montante), t (durata in anni) e i (tasso di interesse


annuo)

dati in uscita: C (capitale iniziale) e I (interesse)

La differenza sostanziale rispetto al caso precedente `e che in questo caso i dati


in uscita sono 2 e non uno solo.

Proviamo a dichiarare la procedura come segue:


> capInter_IntComp := proc(M, t, i)

> M/(1+i)^t;

> M-C

> end;

capInter IntComp := proc(M, t, i) M (i + 1)t ; M C end proc
nessuna segnalazione derrore, ma ci` u non significa che la procedura (quando
eseguita) fornisca i risultati corretti; infatti, se proviamo ad effettuare una
chiamata della procedura (con M = 2000 euro, t = 3 anni e i = 11 %):
> capInter_IntComp(2000,3,0.11);

2000 C

C`e qualcosa che non va: la procedura dovrebbe stampare 2 numeri e invece
stampa unespressione con una C di troppo: come mai ? Lespressione
rappresenta il montante (che `e 2000, giusto) e corrisponde allultima istruzione
(prima dellend), ma al posto della variabile C dovrebbe esserci il valore del
capitale calcolato nellistruzione che precede. Gi` a, ma noi non abbiamo
specificato che il risultato di tale istruzione sia memorizzato in C; per farlo
aggiungiamo una assegnazione nella seconda riga e torniamo a dichiarare la
procedura:
> capInter_IntComp := proc(M, t, i)

> C := M/(1+i)^t;

> M-C;

> end;

Warning, C is implicitly declared local to procedure


capInter_IntComp

capInter IntComp := proc(M, t, i) local C; C := M (i + 1)t ; M C end proc

La nuova dichiarazione d` a una segnalazione di Warning (`e un tipo di errore


non grave che consente comunque lesecuzione della procedura), tale
segnalazione ci avverte che la variabile C `e definita implicitamente, ovvero `e
utilizzata nella procedura senza essere variabile di input e senza che Maple sia
stato avvisato in altro modo del suo utilizzo. Evidentemente Maple preferisce
una dichiarazione esplicita delle variabili utilizzate. La riscrittura della
procedura fatta da Maple ci suggerisce infatti quali sono le sue preferenze;
daccordo, copiamo e riproviamo:
> capInter_IntComp := proc(M, t, i) local C;
> C:=M/(1+i)^t;

> M-C

> end;

capInter IntComp := proc(M, t, i) local C; C := M (i + 1)t ; M C end proc

La segnalazione di Warning `e scomparsa; rifacciamo la chiamata:


> capInter_IntComp(2000,3,0.11);

537.617237

Benino: questo `e il valore corretto dellinteresse, ma dov`e il valore del capitale


(la procedura nelle nostre intenzioni dovrebbe avere 2 valori in uscita ) ?
La risposta `e: loutput fornito automaticamente `e un solo numero; infatti in
Maple una procedura, salvo indicazioni diverse, restituisce un solo numero
ovvero il risultato dellultima istruzione.

Per visualizzare il valore del capitale `e sufficiente aggiungere unistruzione di


stampa:
> capInter_IntComp := proc(M, t, i) local C;

> C:=M/(1+i)^t;

> print(C);
> M-C

> end;

capInter IntComp := proc(M, t, i) local C; C := M (i + 1)t ; print(C) ; M C end proc

nessuna segnalazione derrore; proviamo ad eseguire:


> capInter_IntComp(2000,3,0.11);

1462.382763
537.617237

ora ci siamo, i due valori sono rispettivamente il capitale (stampato con


listruzione print) e linteresse (fornito come output automaticamente essendo
stato calcolato con lultima istruzione della procedura).

Un modo, di pi` u chiara leggibilit`


a, per ottenere entrambi i valori `e quello di
stabilire esplicitamente qual`e loutput della procedura utilizzando listruzione
return, la cui sintassi `e return(espressione). Cambiamo allora nuovamente la
dichiarazione della procedura:
> capInter_IntComp := proc(M, t, i) local C;

> C:=M/(1+i)^t;

> return(C,M-C);

> end;

capInter IntComp :=

proc(M, t, i) local C; C := M (i + 1)t ; return C, M C end proc

Cos` la chiamata della procedura fornisce come output un vettore di due


numeri:
> capInter_IntComp(2000,3,0.11);

1462.382763, 537.617237

A tale output possiamo anche assegnare un nome, ad esempio


> risultato:=capInter_IntComp(2000,3,0.11);

risultato := 1462.382763, 537.617237


In questo modo i numeri ottenuti allinterno della procedura possono essere
utilizzati come fossero due variabili qualsiasi allesterno della procedura stessa;
ad esempio con
> risultato[1]+risultato[2];
2000.000000

ricalcoliamo il montante M.

Ancora unosservazione circa i ; (punti e virgola): nellultima versione la


procedura ha 3 istruzioni (calcolo di C, stampa di C e calcolo dellinteresse)
ed il ; c`e dopo le prime due istruzioni ma non dopo la terza. La ragione sta
nel fatto che il ; serve a separare 2 istruzioni successive; quindi `e facoltativo
metterlo dopo lultima istruzione (quella prima dellend) perchE ` lend non `e
considerata unistruzione, mentre `e obbligatorio negli altri casi e se manca `e
segnalato un errore. Se ad esempio togliamo il ; dopo la prima istruzione:
> capInter_IntComp := proc(M, t, i) local C;
> C:=M/(1+i)^t;

> print(C);

> M-C

> end;

capInter IntComp := proc(M, t, i) local C; C := M (i + 1)t ; print(C) ; M C end proc

`e restituito un errore di sintassi e la dichiarazione della procedura non `e stata


accettata da MAPLE.

6.2 6.2 Istruzioni condizionali


6.2.1 6.2.1 Listruzione if-then-else
Supponiamo di voler calcolare il periodo di tempo per cui deve essere investito
un capitale C in modo da ottenere il montante M se gli interesse sono
calcolati al tasso annuo i con capitalizzazione composta. Una procedura che
calcola la durata dellinvestimento `e ad esempio:
> tempo_IntComp := proc(M, C, i)

> log[1+i](M/C);
> end proc;

tempo IntComp := proc(M, C, i) logi+1 (M C) end proc

([i+1] indica la base del logaritmo).


C = 5000 A
Quindi, se M = 8000 A, e i = 4 %, la durata dellimpiego, in
anni, deve essere:
> tempo_IntComp(8000,5000,0.03);
15.90063174

Proviamo unaltra chiamata della procedura:


> tempo_IntComp(8000,0,0.03);

Error, (in tempo_IntComp) numeric exception: division by zero

Errore: cos`e successo? Rispetto alla chiamata precedente il capitale (che `e il


secondo argomento attuale) `e uguale a zero, ma nella procedura si divide per il
capitale C e quindi occorrerebbe controllare che C non sia nullo. Meglio
ancora sarebbe controllare che il capitale utilizzato nei calcoli sia positivo: per
C minore o uguale a zero sarebbe simpatico stampare un messaggio di errore.
Per effettuare questo controllo si pu`
u utilizzare unistruzione condizionale che
lavori nel seguente modo:

- se C <= 0 allora:

- stampa un messaggio di errore

- altrimenti:

- calcola il tempo di impiego del capitale

Per realizzare questo controllo utilizziamo listruzione


if-then-else di Maple. Si tratta in realt` a di unistruzione presente con analoga sintassi in tutti i
> tempo_IntComp := proc(M, C, i)
> if C <= 0 then

> print("il capitale devessere positivo")

> else

> log[1+i](M/C)
> end if

> end proc;

tempo IntComp := proc(M, C, i)



if C 0 then print(il capitale devessere positivo) else logi+1 (M C) end if
end proc
Se ora rifacciamo la chiamata con capitale nullo otteniamo:
> tempo_IntComp(8000, 0, 0.03);

il capitale devessere positivo


altrimenti:
> tempo_IntComp(8000, 1500, 0.03);

56.63207933

In generale la sintassi dellistruzione condizionale if-then-else `e la seguente:

if espressione boolean then

sequenza 1 di istruzioni MAPLE

else

sequenza 2 di istruzioni MAPLE

end if

e lavora nel seguente modo:

- valuta lespressione boolean (unespressione boolean `e unespressione il cui


risultato pu`u essere soltanto VERO

oppure FALSO; nellesempio lespressione boolean era: C <= 0)

- se il risultato dellespressione boolean `e VERO allora:

- esegui la sequenza 1 di istruzioni MAPLE

- altrimenti:

- esegui la sequenza 2 di istruzioni MAPLE

Si sarebbe anche potuto scrivere la procedura nel seguente modo: se C `e


maggiore di zero allora calcola la durata, altrimenti stampa un messaggio; in
tal caso la procedura diventa:
> tempo2_IntComp := proc(M, C, i)
> if C > 0 then

> log[1+i](M/C)

> else

> print("il capitale devessere positivo")


> end

> end ;

tempo2 IntComp := proc(M, C, i)



if 0 < C then logi+1 (M C) else print(il capitale devessere positivo) end if
end proc
e lavora sostanzialmente nello stesso modo della procedura precedente
tempo IntComp; proviamo come esempio le chiamate con gli stessi argomenti:
> tempo2_IntComp(8000, 1500, 0.03);

56.63207933
> tempo2_IntComp(8000, 0, 0.03);

il capitale devessere positivo

Si osservi che nellultima procedura la fine dellistruzione if-then-else `e stata


segnalata da end (il primo) anzichE ` da end if e, analogamente, end proc `e
stata sostituita da end (quello dellultima riga). In realt`a infatti per Maple le
parole proc ed if (e altre che utilizzeremo tra poco) indicano a Maple linizio
di un particolare gruppo di istruzioni e sono come delle parentesi aperte:
ciascun end `e come una parentesi chiusa corrispondente allultima
parentesi aperta.

In altri linguaggi di programmazione la parentesi aperta `e indicata


` le parole begin - end
esplicitamente dalla parola begin, in altri ancora anzichE
si utilizzano proprio una parentesi graffa aperta e una parentesi graffa chiusa.

6.2.2 6.2.2 Listruzione if

Riprendiamo lesempio della sezione precedente: se si desidera fare il controllo


che C sia non nullo, ma non interessa la stampa del messaggio, allora si pu` u
utilizzare listruzione if:
> tempo3_IntComp := proc(M, C, i)

> if C > 0 then

> log[1+i](M/C)

> end if
> end;

tempo3 IntComp := proc(M, C, i) if 0 < C then logi+1 (M C) end if end proc

in questo caso se C <= 0 non viene stampato alcun messaggio:


> tempo3_IntComp(8000,0,3.5);

In generale la sintassi dellistruzione condizionale if `e la seguente:

if espressione boolean then

sequenza di istruzioni MAPLE

end if
e lavora nel seguente modo:

- valuta lespressione boolean (nellesempio `e C <> 0)

- se il risultato dellespressione boolean `e VERO allora:

- esegui la sequenza di istruzioni MAPLE

6.2.3 6.2.3 Espressioni boolean

Nellesempio della sezione 2.2 (calcolo del tempo di impiego di un capitale C al


tasso di interesse composto i per ottenere un montante M) si `e inserito un
controllo che C sia maggiore di zero:
> tempo3_IntComp := proc(M, C, i)
> if C > 0 then

> log[1+i](M/C)

> end if

> end;

tempo3 IntComp := proc(M, C, i) if 0 < C then logi+1 (M C) end if end proc

ma se esaminiamo il campo di esistenza dellespressione log[i+1](M/C)


(supponendo il tasso di interesse i costante) ci rendiamo conto che il controllo
C > 0 non `e sufficiente, occorre anche che M/C (largomento del logaritmo)
` si deve
sia > 0 ovvero, in altri termini, il montante M devessere positivo, cioE
avere:

M>0eC>0

evidentemente questa `e unespressione boolean (pu` u solo essere o VERA o


FALSA) quindi, per realizzare il controllo, basta inserire lespressione in
unistruzione if salvo sostituire la congiunzione e con la corrispondente and
dellinglese (loppure si sostituisce invece con or):
> tempo4_IntComp := proc(M, C, i)

> if M > 0 and C > 0 then

> log[1+i](M/C)
> end if

> end;

tempo4 IntComp :=

proc(M, C, i) if 0 < M and 0 < C then logi+1(M C) end if end proc
Gli operatori or (somma logica) e and (prodotto logico) sono detti
operatori boolean e lavorano in modo simile agli usuali operatori aritmetici
+ e *, salvo che se scriviamo x + y, le variabili x ed y devono rappresentare
dei numeri, mentre se scriviamo x or y, le variabili x ed y devono assumere
solo i valori true (VERO) oppure false (FALSO).

La descrizione completa degli operatori or e and `e data dalle loro tabelle di


verit`
a in cui sono forniti i risultati per tutti i possibili valori degli operandi.

Lopertore or d` a come risultato FALSO solo se entrambi gli operandi sono


falsi, quindi la sua tabella di verit`
a `e:

x y x or y

false false false

false true true

true false true

true true true

invece lopertore and d` a come risultato VERO solo se entrambi gli operandi
sono veri e la sua tabella di verit`
a `e:

x y x and y

false false false

false true false

true false false

true true true

un altro operatore boolean `e il not (negazione logica), la cui tabella di


verit`
a `e:

x not x

false true

true false

Gli operatori boolean or, and e not insieme con i valori false e true
costituiscono unalgebra (analoga a quella usuale sui numeri reali) detta
algebra di Boole.
Nellalgebra di Boole si possiamo valutare espressioni in cui si utilizzano solo
gli operatori boolean e le variabili possono assumere solo i valori true e false;
espressioni di questo tipo sono dette espressioni boolean. Un esempio di
espressione boolean `e:

x or y and (x or y and not x)

Naturalmente per valutare unespressione boolean dobbiamo sapere in quale


ordine si devono valutare gli operatori; ad esempio per valutare lespressione

x or y and not x

qualoperatore da valutare per primo ? E lor, land o il not ? Lordine di


valutazione (o pi`
u precisamente la priorit`a degli operatori bobolean) `e:
not, and, or (cos` come nellalgebra sui numeri reali la priorit`
a `e: elevamento
a potenza, prodotto, somma).

6.3 6.3 Istruzioni iterative


6.3.1 6.3.1 Listruzione while

Nella risoluzione di un problema pu` u accadere che un gruppo di istruzioni


debba essere ripetuto finchE` continua a verificarsi una determinata condizione.
Consideriamo ad esempio il seguente problema: si investe un capitale C in
unoperazione finanziaria al tasso di interesse annuo i (capitalizzazione
composta) e si desiderano calcolare tutti i montanti dopo 1 anno, dopo 2 anni,
` il montante non abbia raggiunto un certo valore Mfin.
eccetera, finchE
Desideriamo cio`e calcolare e stampare gli importi dei montanti:

C*(1+i)1, C*(1+i)2, C*(1+i)3, . . .C*(1+i)n


` continua a valere la condizione C*(1+i)n < Mfin .
continuando finchE

I dati del problema sono in questo caso:

dati in ingresso: C (capitale iniziale), i (tasso di interesse annuo) e Mfin


(importo finale del montante)

` C*(1+i)n
dati in uscita: i montanti dopo 1 anno, 2 anni, 3 anni, ... finchE
< Mfin
Per effettuare la stampa dobbiamo perci`u riutilizzare sempre la stessa formula
ma per valori diversi del numero di anni, che indicheremo con n; i passi da
eseguire sono perci`u:

- inizializza n (numero di anni) ad 1


` C*(1+i)n < Mfin esegui:
- finchE
- stampa C*(1+i)n
- aumenta n di 1

Si tratta ora di tradurre questi passi in istruzioni MAPLE tenendo conto che:

inizializzare n ad 1 significa assegnare ad n il valore 1;

il comando finchE ` ... esegui si traduce con listruzione while ... do


di Maple; anche con questa istruzione sar` a necessario indicare la fine delle
istruzioni da ripetere con end do (oppure anche semplicemente con end);

per aumentare n di 1 si utilizza loperazione di assegnazione n := n + 1


il cui effetto `e quello di assegnare alla variabile n un nuovo valore uguale
a quello che aveva prima aumentato di 1.

Ecco dunque la procedura che esegue quanto richiesto:

> montanti_IntComp := proc(C, i, Mfin) local n;


> n:=1;
> while C*(1+i)^n < Mfin do
> print(C*(1+i)^n);
> n:= n + 1;
> end do
> end;

montanti IntComp := proc(C, i, Mfin)


local n;
n := 1 ; while C (i + 1)n < Mfin do print(C (i + 1)n ) ; n := n + 1 end do
end proc
Si osservi che la variabile n `e dichiarata locale per evitare la solita fastidiosa
segnalazione di Warning descritta in sez. 6.1.3.

Vediamo ad esempio quali sono i montanti anno dopo anno che consentono ad
di raddoppiare al tasso annuo del 4 %:
un capitale C = 1000 A
> montanti_IntComp(1000, 0.04, 2000);

1040.00
1081.6000
1124.864000
1169.858560
1216.652902
1265.319018
1315.931779
1368.569050
1423.311812
1480.244285
1539.454056
1601.032219
1665.073507
1731.676448
1800.943506
1872.981246
1947.900496
18

Lultimo numero stampato `e il valore di n al termine della procedura (infatti


listruzione che aumenta n `e lultima della procedura) e rappresenta il numero
di anni necessari per raggiungere Mfin = 2000 A. Si osservi che le istruzioni
allinterno del while sono state ripetute 17 volte, ci`
u si esprime dicendo che ci
sono state 17 iterazioni del ciclo while.

In generale listruzione while ha la seguente sintassi:

while espressione boolean do

sequenza di istruzioni MAPLE

end do

e impone a Maple le seguenti operazioni:


- valuta lespressione boolean (nellesempio `e C*(1+i)n < Mfin)

- se il risultato dellespressione boolean `e VERO allora:

- esegui la sequenza di istruzioni MAPLE (detta corpo dellistruzione while)

- ripeti dallinizio (valuta ..eccetera)

- altrimenti termina

Attenzione! Pu` u accadere, per errore, di scrivere come condizione per


lesecuzione del corpo dellistruzione while una espressione boolean sempre
vera: questo avviene ad esempio, se nella condizione dellistruzione while della
procedura montanti IntComp si sostituisce

C*(1+i)n < Mfin con - C*(1+i)n < Mfin

In tal caso ripetendo la chiamata

montanti IntComp(1000, 0.04, 2000);

lespressione boolean dellistruzione while `e sempre vera e il corpo


dellistruzione viene continuamente ripetuto (per arrestare lelaborazione
cliccare sul pulsante con lindicazione di STOP). In questi casi si dice che si ha
un ciclo infinito o loop infinito.

6.3.2 6.3.2 Listruzione for

Spesso quando alcune istruzioni devono essere ripetute pi` u volte si conosce
preventivamente il numero esatto di ripetizioni richieste. In questi casi
conviene utilizzare listruzione for anzich`
e la while.

Partiamo anche in questo caso da un problema: supponiamo di voler calcolare


il fattoriale del numero n (ci dimentichiamo per un attimo che in Maple il
fattoriale di un numero n si calcola semplicemente scrivendo n!).

Costruiamo anche qui una procedura che contenga la nuova istruzione.

Abbiamo in questo caso:

dato in ingresso: n
dato in uscita: il fattoriale di n

Una procedura che calcola il fattoriale di un numero `e:

> fattoriale := proc(n) local m, fatt;


> fatt:=1;
> if n>0 then
> for m from 1 to n do
> fatt := fatt*m;
> end do;
> end if;
> return(fatt)
> end;

fattoriale := proc(n)
local m, fatt;
fatt := 1 ; if 0 < n then for m to n do fatt := m fatt end do end if ; return fatt
end proc

Che possiamo richiamare per calcolare il fattoriale di 6:

> fattoriale(6);
720

La sintassi dellistruzione for (nella sua forma pi`


u semplice) `e:

for variabile indice from valore iniziale to valore finale do

sequenza di istruzioni MAPLE

end do

e lavora nel seguente modo:

- variabile indice := valore iniziale


` variabile indice <= valore finale esegui:
- finchE

- esegui la sequenza di istruzioni MAPLE

- variabile indice := variabile indice + 1


Un esempio pi`
u elaborato di utilizzo dellistruzione for

Supponiamo di voler calcolare lintegrale definito:

noti gli estremi di integrazione a e b. Non esiste in questo caso alcun modo di
scrivere una primitiva della funzione integranda utilizzando composizioni di
funzioni elementari, possiamo per` u calcolare un valore approssimato
dellintegrale applicando la definizione: approssimiamo cio`e larea
rappresentata dallintegrale con larea di un plurirettangolo.

I dati del problema sono perci`


u:

dati in ingresso: a e b (estremi dellintervallo di integrazione) e m (numero


delle parti uguali in cui si intende suddividere lintervallo di integrazione)

dato in uscita: valore dellintegrale

Di seguito sono descritti i passi da eseguire per ottenere una soluzione del
problema:

- inizializzare a zero una variabile (area) in cui memorizzare la somma delle


aree dei rettangoli che costituiscono il

plurirettangolo

- inizializzare una variabile (delta) con il valore (b - a)/m (`e la lunghezza di


ciascuna delle m parti in cui viene suddiviso lintervallo [a,b])

- inizializzare con a (estremo sin. dellintervallo di integrazione) una variabile


(x) che rappresenti il generico punto

x = a + n * delta al variare di n = 1, 2, , ..., m

- per n = 1, 2, , ..., m esegui:

- calcola il nuovo valore di x aggiungendo delta al valore attuale di x


- calcola il nuovo valore di area aggiungendo larea del rettangolo di base
delta ed altezza exp(x2), al valore

attuale di area

- restituisci il valore di area (area del plurirettangolo) calcolato

che tradotto in istruzioni MAPLE diventa:


> integrale := proc(a,b,m) local n, area, x, delta;

> area := 0;

> delta := (b - a) / m;

> x := a;
> for n from 1 to m do

> x := x + delta;

> area := area + delta*exp(x^2);

> od;
> return(evalf(area))

> end;

integrale := proc(a, b, m)
local n, area, x, ;
area := 0 ;

:= (b a) m ;
x := a ;
for n to m do x := + x ; area := area + exp(x2 ) end do ;
return evalf(area)
end proc
Osservazioni:

il comando evalf (espressione) restituisce il valore di unespressione (reale)

al solito le variabili che non sono argomenti formali della procedura (n,
area, x e delta) sono dichiarate come variabili locali per evitare la seg-
nalazione di Warning

listruzione for incrementa automaticamente la variabile n


Proviamo a fare qualche chiamata: integrando nellintervallo [1,3] con m =
1000:
> integrale(1,3,1000);

1451.199053

... con m = 2000:


> integrale(1,3,2000);

1447.136700

... e con m = 3000:


> integrale(1,3,3000);

1445.784397

si osservi che il valore approssimato dellintegrale diminuisce, infatti


lapprosimazione `e fatta per eccesso dato che il valore x `e lestremo destro dei
sotto-intervalli e che la funzione integranda `e strettamente crescente. Per
ottenere unapprosimazione per difetto basta far variare n da 0 ad m - 1.

Naturalmente a Maple di calcolare lintegrale utilizzando il comando int di


Maple:
> evalf(int(exp(x^2),x=1..3));

1443.082472

You might also like