Linguaggio C++ Un esempio: Calcolo della potenza n-esima di un numero reale Funzioni

Preview:

Citation preview

Linguaggio C++

Un esempio:Calcolo della potenza n-esima di un

numero reale

Funzioni

Nella fase d’implementazione di un programma, come

nella fase di analisi del problema, è consigliabile

suddividere il codice in tante parti, ciascuna delle

quali risolve un particolare aspetto del problema. Tali

parti, in C++, prendono il nome di funzioni

La loro struttura è del tutto simile a quella già vista

per il main: un insieme di dati e istruzioni,

racchiusi tra parentesi graffe cui è associato un

nome e che ritorna un valore. Al momento del

runtime, il nome della funzione scritto all’interno di

un segmento di programma, provoca l’esecuzione

dell’insieme d’istruzioni associato

Per affrontare il tema delle funzioni si analizza,

come pretesto, il problema del calcolo della potenza

intera di un numero reale supponendo di

coinvolgere nella sua risoluzione più gruppi di

persone. Si vedrà come l’uso delle funzioni

semplifichi questo compito, permettendo altresì di

scrivere il programma in un formato più leggibile,

compatto ed elegante

Si desidera scrivere un programma che calcoli la

potenza n-esima di un numero reale x:

nxpotenza

con n intero, positivo o negativo

Analisi del problema

La prima versione dell’algoritmo risolutivo è

ancora molto semplice:

Potenza di un numero reale

{

Acquisisci il valore di x e di n

Calcola la potenza

Comunica il risultato

}

Evidenziati gli aspetti fondamentali del problema

(top), si procede scomponendoli in fasi più semplici,

fino ad arrivare a una forma non più divisibile

(down).

Se l’esempio proposto facesse realmente parte di un

grande progetto, alcuni componenti del gruppo di

lavoro potrebbero non conoscerne i dettagli. Ognuno

di loro, o in piccoli gruppi, si occuperà di una fase

cercando di sfruttare al meglio le proprie competenze

specifiche

Gli algoritmi rappresentati di seguito potrebbero

costituire un primo esempio di tale lavoro:

Acquisisci il valore di x e di n si occupa di

acquisire dalla tastiera il valore della base x e

dell’esponente n e non necessita di ulteriori

scomposizioni

L’algoritmo Calcola la potenza si occupa di

calcolare il valore della potenza n-esima di x

tenendo conto che se n è negativo la potenza è data

dal reciproco della potenza (positiva) di x:

nn

xx

1

Calcola la potenza{ SE (n >= 0) esponente n ALTRIMENTI { esponente –n Calcola la potenza positiva SE (n < 0) potenza 1 / potenza}

Sviluppando il blocco Calcola la potenza si

ottiene:

Come si nota, nella fase di scomposizione di questo

algoritmo è stato necessario ricorrere ad un’altro

algoritmo, Calcola la potenza positiva, che

calcolerà il valore della potenza n-esima (positiva) di

x. In linguaggio di programmazione, questa scelta

“naturale” si tradurrà nella chiamata della funzione

specializzata in questo compito

Calcola la potenza positiva{ potenza 1 numeroVolte 1 FINCHÉ (numeroVolte <= esponente) { potenza potenza · x numeroVolte numeroVolte + 1 }}

L’algoritmo Calcola la potenza positiva moltiplica x per sé stessa per esponente – 1

volte, ovvero eleva x a esponente:

Se esponente è 0 non viene effettuata nessuna moltiplicazione perché x0 vale 1

L’algoritmo Comunica il risultato ha il compito

di comunicare il valore del polinomio. La

comunicazione può avvenire presentando il valore

sullo schermo, stampandolo, scrivendolo su un file o

inviandolo a un’altra periferica d’uscita. In questo

esempio si suppone di visualizzarlo sullo schermo.

Non sono quindi necessarie ulteriori scomposizioni

Nella fase di trasformazione del programma in C++

questi algoritmi, tranne Acquisisci il valore di x

e di n, sono stati scritti sottoforma di funzione. Sì è

così ottenuto un programma il cui main ha la stessa

chiarezza e semplicità di lettura dell’algoritmo di

base

/* Programma per il calcolo della potenza intera

di un numero reale.

Versione con uso di funzioni */

#include <iostream>

using namespace std;

double x,

potenza; // di x elevata a n

int n, esponente; // esponente ed esponente

assoluto

int numeroVolte; // variabile di ciclo

char op; // carattere di separazione tra x e n

// Funzione che calcola x elevata a esponente

void CalcolaPotenzaPositiva()

{

potenza = 1; // Inizializza la variabile accumulatore

for(numeroVolte = 1; numeroVolte <= esponente;

numeroVolte++)

potenza *= x; // potenza = potenza * x

}

// Funzione che calcola x elevata a n

void CalcolaPotenza() {

// in esponente va il valore assoluto di n

if (n >= 0)

esponente = n;

else

esponente = -n;

CalcolaPotenzaPositiva(); // Chiamata di funzione

// se n è negativo calcola il reciproco

if (n < 0)

potenza = 1 / potenza;

}

void ComunicaRisultato(){

cout << "Il valore della potenza e': “

<< potenza << endl;

}

// Funzione principale del programma

int main(){

// Acquisisci il valore della x e di n

cout << "Scrivi la potenza da calcolare ”

"nel formato x^n: ";

cin >> x >> op >> n;

CalcolaPotenza(); // Chiamata di funzione

ComunicaRisultato(); // Chiamata di funzione

}

Si osservi come la struttura delle funzioni utilizzate

dal programma sia simile a quella della funzione

principale main. Ognuna di esse, infatti, costituisce

un vero e proprio sottoprogramma, che sarà eseguito

quando richiesto

Definizione e chiamata di una funzione

Ogni funzione è costituita da un’intestazione, in

cui è indicato il nome, e da un corpo dove, tra

parentesi graffe, sono racchiuse le istruzioni che

dovranno essere eseguite quando la funzione verrà

chiamata

Tale struttura prende il nome di definizione di funzione

NomeFunzione()

intestazione

{.........

}

corpo

Per fare in modo che le istruzioni del corpo della

funzione siano eseguite è sufficiente scriverne il

nome seguito dalle parentesi tonde () e dal

carattere terminatore ; :

NomeFunzione();

Questa istruzione prende il nome di chiamata di

funzione

Ogni programma è comunemente costituito da

numerose funzioni, ciascuna delle quali ha lo scopo di

risolvere un determinato problema. Fra queste, ne

esiste una di nome main che stabilisce il punto dal

quale avrà inizio l’esecuzione del programma. Al

main di solito è affidato il compito di controllare la

sequenza del programma

Esecuzione di un programma

Durante l’esecuzione di una chiamata di funzione, il

controllo del programma passa alla prima istruzione

del corpo della funzione. Terminata l’esecuzione del

sottoprogramma, il controllo è restituito alla funzione

chiamante che proseguirà eseguendo l’istruzione

successiva alla chiamata di funzione

int main(){

...CalcolaPotenza();...

}

void CalcolaPotenza(){

...

...

...}

Funzione chiamante

Chiamata di funzione

Funzione chiamata

1. il raggruppamento di un certo numero di istruzioni

sotto un unico nome aumenta la leggibilità del

codice sorgente e ne può ridurre sia la dimensione

sia il tempo necessario per scriverlo;

Vantaggi nell’uso delle funzioni

I principali vantaggi nell’uso delle funzioni si possono

sintetizzare nei seguenti tre punti:

2. nel caso di problemi di complessità elevata, dove è

richiesta la partecipazione di più persone allo

sviluppo di un progetto, l’uso delle funzioni

costituisce senz’altro l’organizzazione più

produttiva, perché permette un’efficiente

suddivisione del lavoro;

3. le funzioni rendono concreta l’analisi dei problemi

con il procedimento top-down

È anche bene ricordare che una funzione può essere

richiamata dall’interno di un’altra funzione

(CalcolaPotenzaPositiva() è stata chiamata

da CalcolaPotenza()). Inoltre, per utilizzare una

funzione non è necessario conoscerne i dettagli

Per esempio, per ottenere il valore di xn è sufficiente

sapere che occorre chiamare la funzione

CalcolaPotenza() inizializzando

opportunamente le sue variabili di ingresso x ed n e

che, dopo la chiamata, il risultato sarà disponibile

nella variabile di ritorno potenza

In questo modo nulla vieta a una funzione scritta per

un programma di essere impiegata per realizzarne un

altro: si possono così organizzare apposite librerie

(sottoforma di file) dalle quali poi richiamare le

funzioni che occorrono, senza la necessità di doverle

riscrivere ogni volta

Questo espediente permette altresì di modificare il

corpo di una funzione (per esempio per correggerla,

renderla più efficiente o mutarne addirittura il

comportamento) senza dover intervenire sul

programma che la utilizza

Recommended