• Non ci sono risultati.

Il problema dell ordinamento

N/A
N/A
Protected

Academic year: 2022

Condividi "Il problema dell ordinamento"

Copied!
20
0
0

Testo completo

(1)

Il problema dell’ordinamento

Il problema dell’ordinamento

• Dati n elementi sui quali si possa considerare un relazione d’ordine totale (ogni coppia di elementi è confrontabile) costruire la permutazione ordinata, vale a dire trovare una disposizione degli elementi in modo tale che si abbia:

a1< a2< a3< …. < an

• Problema analogo è quello di considerare gli elementi ordinati in ordine decrescente.

(Capitolo 3)

Il problema dell’ordinamento

• Vedremo metodi diversi e ne calcoleremo la complessità.

• I metodi di ordinamento saranno:

-ordinamento scansione (o selezione diretta) - bubblesort

- ordinamento per inserimento - ordinamenti ricorsivi

-quicksort - mergesort

• La complessità varia da O(n2) a O(n····log2n)

Ordinamento per scansione

Analisi.

• Vogliamo mettere gli elementi nell’ordine:

a1< a2< a3< …. < an

• Osserviamo che:

a1è il minimo tra gli elementi {a1, a2, … an} a2è il minimo tra gli elementi {a2, a3, … an} . . .

an-1è il minimo tra gli elementi {an-1, an} anè al suo posto.

Ordinamento per scansione

Progetto.

• Cerchiamo un modo per avere al primo posto il minimo tra tutti, al secondo posto il minimo tra a2 e i rimanenti, al posto (n-1)-esimo il minimo tra an-1e an.

• Avremo una struttura iterativa che “mette a posto” gli elementi da 1 a n-1, dove “mettere a posto” significa:

mettere al posto i-esimo l’elemento minimo tra aie gli elementi rimanenti.

Ordinamento per scansione

mentre ci sono elementi da ordinare eseguire mettere all’i-esimo posto il minimo

degli elementi {ai, ai+1, …., an} //finementre

• La struttura iterativa “mentre ci sono elementi da ordinare” sarà un ciclo del tipo:

per i da 1 a n-1 eseguire

(2)

Ordinamento per scansione

Cerchiamo un modo per: trovare il minimo.

Abbiamo due strategie:

• I. considerare gli elementi

ai e ak con k = i+1, …, n e scambiarli se non sono nell’ordine

• II. calcolare il valore e la posizione del minimo ed eseguire un solo scambio tra aie il minimo trovato.

Ordinamento per scansione

• Come si effettua lo scambio del valore tra due variabili?

• Consideriamo due variabili x e y, vogliamo scambiare il loro contenuto:

prima dopo

x y x y

7 5 5 7

Ordinamento per scansione

Non possiamo fare subito l’assegnazione x=y altrimenti x e y avrebbero lo stesso valore.

Dobbiamo utilizzare una variabile di supporto, s, dello stesso tipo di x e y, per depositare temporaneamente uno dei due valori:

1) s=x; x y

2) x=y;

3) y=s;

s

Uno scambio si fa con 3 assegnazioni

7 5 7 7 5

Ordinamento per scansione

//ordinamento per scansione con scambio per i da 1 a n-1 eseguire

//mettere in aiil minimo tra ai , ai+1 , …, an per k da i+1 a n eseguire

se a[i] > a[k]

allora //scambiare ai con ak s ← a[i]

a[i] ← a[k]

a[k] ← s //finese

//fineper

//fineper //ciclo esterno

Ordinamento per scansione

• Calcoliamo la complessità dell’algoritmo per scansione.

• L’operazione fondamentale eseguita nella struttura iterativa è il confronto: questo viene eseguito sempre, mentre lo scambio viene eseguito solo nel caso vero.

• Quanti confronti vengono eseguiti?

• Il ciclo esterno varia da 1 a n-1, il ciclo interno varia da i a n: i non è fisso e quindi il calcolo esatto è un po’ più laborioso.

Ordinamento per scansione

n° iterazione elementi n° confronti i=1 (a1, a2) (a1, a3) … (a1, an) n-1 i=2 (a2, a3) … (a2, an) n-2

…… …….

i=n-1 (an-1, an) 1

Sommiamo i confronti:

1 + 2 + 3 + …. + n-2 + n-1= n·(n-1)/2

(3)

Ordinamento per scansione

• Un modo facile per ricordare la somma (uno dei due numeri interi n o n-1 è pari) è:

(il primo + l’ultimo) ×××× (metà del numero di elementi presenti nella formula)

• Si può dimostrare la formula per induzione (progressione aritmetica).

• Verifichiamo ad esempio per n=7:

1 + 2 + 3 + 4 + 5 + 6 = (1 + 6) ××× 6/2 = 7 ×× ××× 3 =

= 21

Ordinamento per scansione

• Caso peggiore.

• All’interno dell’iterazione si fanno tutti i confronti e tutti gli scambi.

• Dati: vettore è ordinato in ordine inverso a = (8, 6, 5, 3, -2 -7)

n(n-1)/2 confronti + 3n(n-1)/2 assegnazioni Quindi O(n2/ 2).

Ordinamento per scansione

• Caso favorevole.

• Si fanno tutti i confronti e nessuno scambio

• Dati: vettore già ordinato a = (2, 4, 5, 8, 20, 34, 51) n(n-1)/2 confronti + 0 assegnazioni Quindi Ω(n2/2)

Ordinamento per scansione

• L’algoritmo di ordinamento lineare con scambio ha complessità:

• O(n2/2) nel caso peggiore (limitazione superiore)

• Ω(n2/2) nel caso favorevole (limitazione inferiore)

• Pertanto

Θ(n2/ 2)

Ordinamento per scansione

• Se vogliamo ordinare l’array tenendo conto del valore del minimo e della sua posizione, dobbiamo avere una variabile min, per memorizzare il valore minimo, e un indice imin per memorizzare la posizione.

• Possiamo anche utilizzare la sola variabile imin e accedere al valore del minimo tramite a[imin].

• Con questa seconda scelta si fanno meno assegnazioni.

• Esercizio: verificare l’affermazione.

Ordinamento per scansione

//ordinamento per scansione con minimo per i da 1 a n-1 eseguire

//mettere in aiil minimo tra ai , ai+1 , …, an imin← i

per k da i+1 a n eseguire se a[imin] > a[k]

allora imin← k //finese

//fineper

(4)

Ordinamento per scansione

//dopo il ciclo interno si deve mettere aimin // al posto di ai: scambiare ai con aimin s ← a[i]

a[i] ← a[imin]

a[imin] ← s

//fineper //ciclo esterno

Ordinamento per scansione

Caso peggiore.

• All’interno dell’iterazione il confronto dovrà essere sempre vero. In realtà ciò non si verifica per tutte le iterazioni, perché con lo scambio si ordina anche la seconda parte dell’array.

• Dati: vettore è ordinato in ordine inverso confronti: n (n-1) / 2

assegnazioni:

4(n-1) (ciclo esterno) + n(n-1)/2 (al più nel ciclo interno)

Ordinamento per scansione

Caso favorevole.

• Si fanno tutti i confronti e solo le assegnazioni del ciclo esterno.

• Dati: vettore già ordinato

confronti: n (n-1) / 2

assegnazioni: 4(n-1) (solo nel ciclo esterno)

Ordinamento per scansione

• Le operazioni dei due algoritmi hanno un costo diverso: uno scambio richiede tre assegnazioni; lo scambio è una operazione

“costosa”.

• Confrontiamo le due versioni:

• Il numero di confronti nei due algoritmi è uguale ed è sempre:

n(n-1) / 2

(un confronto è “più costoso” di una assegnazione)

Ordinamento per scansione

• Varia il numero di assegnazioni:

nel caso favorevole si ha:

0 (scambio) 4(n-1) (minimo) nel caso peggiore si ha:

3(n-1)n /2 (scambio) (n-1)n / 2 + 4(n-1) (minimo)

• Verificare che per n>4

3(n-1)n /2 > (n-1)n / 2 + 4(n-1)

Ordinamento bubblesort

• Si eseguono confronti tra elementi successivi:

(a1, a2) (a2, a3) (a3, a4) … (an-1, an) e se gli elementi non sono nell’ordine allora si scambiano. Con questa tecnica la componente con valore più grande va in fondo (al posto di an):

(9, 2, 8, 10, 1, 4) diventa (2, 8, 9, 1, 4, 10)

• Si ricomincia dell’inizio, dalla coppia (a1, a2), e si “mette a posto” an-1, poi an-2, … , infine a2.

(5)

Ordinamento bubblesort

• Si può partire dalla fine del vettore, iniziando il confronto dalla coppia (an-1, an) e andare indietro. Con questa tecnica la componente con valore più piccola va al posto di a1:

(9, 2, 8, 10, 1, 4) diventa (1, 9, 2, 8,10, 4)

• In questo caso si ricomincia nuovamente dalla coppia (an-1, an) e si mette in ordine a2, poi a3si continua fino ad an-1.

Ordinamento bubblesort

Progetto.

• Consideriamo la prima versione: si inizia sempre dalla coppia (a1, a2); l’indice del ciclo che esegue i confronti è l’indice della prima componente della coppia. Alla prima iterazione varia da 1 a n-1 (si mette in ordine an), nella seconda iterazione l’indice varia da 1 a n-2 (si mette in ordine an-1); nella terza iterazione l’indice varia da 1 a n-3 (si mette in ordine an-2);

ecc. nell’ultima iterazione l’indice varia da 1 a n-(n-1)=1 (si mette in ordine a2); con l’ultimo confronto è in ordine anche a1.

Ordinamento bubblesort

//ordinamento bubblesort: prima versione per i da 1 a n-1 eseguire

per k da 1 a n-i eseguire se a[k] > a[k+1]

allora //scambiare ak con ak+1 s ← a[k]

a[k] ← a[k+1]

a[k+1] ← s //finese

//fineper //fineper

Ordinamento bubblesort

• Quanti confronti?

n° iterazione elementi n° confronti

i=1 (a1, a2) (a2, a3) … (an-1, an) n-1 i=2 (a1, a2) … (an-2, an-1) n-2

…… …….

i=n-1 (a1, a2) 1

Ordinamento bubblesort

• I confronti vengono sempre eseguiti: se il confronto risulta vero si esegue lo scambio, se risulta falso non si esegue lo scambio.

• Sommiamo i confronti:

1 + 2 + 3 + …. + n-2 + n-1= n·(n-1)/2 (come per l’ordinamento per scansione)

Ordinamento bubblesort

• Quante assegnazioni?

Caso favorevole.

0 assegnazioni (già ordinato)

• Caso peggiore.

3·n·(n-1)/2 (ordine inverso)

• Pertanto anche il bubblesort è Θ(n2/ 2).

(6)

Confronto tra i vari metodi di ordinamento

• Consideriamo il seguente array e vediamo come si muovono gli elementi (alla prima iterazione).

a = ( 40, 20, 1, 7, 10, 0) n=6 1) lineare con scambio

40 20 1 7 10 0 scambio 40, 20 20 40 1 7 10 0 scambio 20, 1 1 40 20 7 10 0 scambio 1, 0 0 40 20 7 10 1

Confronto tra i vari metodi di ordinamento

2) lineare con minimo 40 20 1 7 10 0

imin 1 2 3 6 scambio 40, 0

0 20 1 7 10 40 3) bubblesort (massimo in fondo)

40 20 1 7 10 0 scambio 40, 20 20 40 1 7 10 0 scambio 40, 1 20 1 40 7 10 0 scambio 40, 7 20 1 7 40 10 0 scambio 40, 10 20 1 7 10 40 0 scambio 40, 0

20 1 7 10 0 40

Confronto tra i vari metodi di ordinamento

4) bubblesort (minimo in testa)

40 20 1 7 10 0 scambio 0, 10 20 40 1 7 0 10 scambio 0, 7 20 1 40 0 7 10 scambio 0, 40 20 1 0 40 7 10 scambio 0, 1 20 0 1 40 7 10 scambio 0, 20

0 20 1 40 7 10

Varianti del bubblesort

• Osserviamo che nel bubblesort si confronta una componente con la successiva, akcon ak+1; pertanto, se non ci sono scambi significa che l’array è ordinato.

• Esempio.

a= (2, 4, 5, 8, 21, 34, 58, 90)

• Le coppie considerate sono:

(2, 4) (4, 5) (5, 8) (8, 21) (21, 34) (34, 58) (58, 90)

Varianti del bubblesort

• Infatti, per la proprietà transitiva della relazione d’ordine < si ha che:

se ak< ak+1 e ak+1< ak+2 allora ak< ak+2

Esercizio1. Costruire una variante di bubblesort che tenga conto che se non si fanno scambi l’array è ordinato.

Suggerimento. Utilizzare una variabile logica ordinato da inizializzare a falso e da inserire nel predicato del ciclo esterno: se non ci sono scambi ordinato deve essere vero.

Varianti del bubblesort

Esercizio2.

• Costruire una variante che tenga conto della posizione dell’ultimo scambio.

• Esempio.

a = ( 3, 1, 2, 5, 7, 8, 9, 12, 34, 35) Nel ciclo interno si effettuano gli scambi:

(3, 1) diventa (1, 3) (3, 2) diventa (2, 3)

i successivi confronti: (3, 5), (5, 7), (7, 9) , ecc.

non comportano altri scambi.

(7)

Varianti del bubblesort

• Memorizzando la posizione dell’ultimo scambio non si “guarda” più la parte di array già ordinato.

• Suggerimento. Chiamare: inizio e fine gli estremi degli indici che limitano la parte di array da ordinare, sc una variabile che memorizza la posizione dell’ultimo scambio;

inizializzare sc con il valore di inizio.

• Quando inizio = fine significa che l’array è ordinato.

Complessità delle varianti del bubblesort

• Per entrambe queste varianti la complessità nel caso favorevole è inferiore a quella del caso senza la variante.

• Infatti, se si fornisce un array già ordinato, dopo la prima iterazione il ciclo termina

• nel primo caso con ordinato=vero

• nel secondo caso con inizio=fine

• Pertanto il caso favorevole è Ω(n).

• Il caso peggiore è sempre O(n2/2).

Esercizio

• Si calcoli la complessità dell’algoritmo seguente, considerando i casi a>b, a=b, a<b;

specificando il numero di assegnazioni e di confronti nei tre casi.

• Si supponga n>0.

• Quale sarebbe il valore di a e b se si stampassero a e b alla fine della struttura iterativa “mentre”?

Esercizio

Algoritmo

definizione variabili a, b, n, i, k intero continua logico acquisire valori per a, b, n

continua ← vero i ← 0

mentre i ≠ n e continua eseguire i ← i+1

se a < b

allora a ← a-1

Esercizio

altrimenti se a == b allora

per k da 1 a n eseguire a ← a+1 b ← b+1 //fineper

altrimenti continua ← falso //finese

//finese //finementre

Costanti

(8)

L’uso delle costanti

• Questo programma effettua un cambio di valuta

• Un utente potrebbe chiedersi quale sia il significato del numero 0.71 usato nel programma, ma anche se questo valore non varierà nel tempo.

int main(){//cambio valuta double dollaro = 2.35;

double euro = dollaro * 0.71;

cout<<dollaro<<" dollari =

"<<euro

<<" euro \n"; }

L’uso delle costanti

• Così come si usano nomi simbolici descrittivi per le variabili, è opportuno assegnare nomi simbolici anche alle costanti utilizzate nei programmi.

• Si hanno dei vantaggi:

1. si aumenta la leggibilità

2. si evitano molte sostituzioni, se il valore della costante deve cambiare

3. non lo si confonde con altri valori.

L’uso delle costanti

1. Aumenta la leggibilità: chiunque usi il nostro programma capisce che 0.71 è il fattore di conversione

int main(){

const double EURO_DOLLARO = 0.71;

double dollaro = 2.35;

double euro = dollaro*EURO_DOLLARO;

cout<<dollaro<<" dollari =

"<<euro

<<" euro \n"; }

L’uso delle costanti

2. Si evitano molte sostituzioni: il valore può cambiare e lo dobbiamo cambiare in ogni istruzione in cui viene usato:

int main(){

const double EURO_DOLLARO = 0.90;

double dollaro1 = 2.35;

double euro1 = dollaro1*EURO_DOLLARO;

double dollaro2 = 3.45;

double euro2 = dollaro2*EURO_DOLLARO;

//cout<<. . . }

L’uso delle costanti

3. Si può confondere con altri valori:

int main(){

const double EURO_DOLLARO = 0.75;

double dollaro1 = 2.35;

double euro1 = dollaro1*EURO_DOLLARO;

double costocaffe = 0.90;

// cout<<. . . }

Definizione di costante

• Sintassi.

(par 13.4.1)

const nometipo NOME_COSTANTE = espressione;

• NOME_COSTANTE è il nome che vogliamo dare alla costante.

• Spesso il nome delle costanti viene scritto usando tutte le lettere maiuscole (es. EURO_DOLLARO componendo due nomi con la sottolineatura); ci si deve ricordare che il linguaggio distingue le maiuscole dalle minuscole.

(9)

Definizione di costante

• Le costanti sono identificate dalla parola chiave const.

• In fase di definizione si deve specificare il tipo della costante e le si attribuisce un

valore

(espressione): tale valore non

può più essere modificato.

• Il tentativo di modificare il valore della costante, dopo l’inizializzazione, produce un errore (semantico) durante la compilazione.

Definizione di costante

• Un uso frequente delle costanti si ha nella definizione degli array: quando si definisce un array si deve sempre indicare, tramite una costante, il numero massimo delle componenti:

il compilatore riserva in memoria uno spazio per quel numero di componenti. Per aumentare la leggibilità, permettere facili sostituzioni e non confondere con altri valori si può definire l’array nel modo seguente:

const int dim = 100;

double a[dim];

Matrici: array a due dimensioni

Matrici

• Vogliamo rappresentare informazioni omogenee (dello stesso tipo) ma descritte da una coppia di indici:

aik i = 1, 2, …, n k = 1, 2, … , m matrice A di n righe e m colonne:

a11 a12 … a1m A = ………….

an1 an2 …. anm

Matrici

• Molti problemi matematici fanno uso di matrici; uno dei problemi più frequenti è la risoluzione di un sistema lineare di n equazioni in n incognite (estensione del sistema 2×××2 che rappresenta il determinare il × punto di intersezione di due rette del piano) e che si può rappresentare algebricamente come prodotto “matrice ×××× vettore”:

A x = b

Matrici

• Definizione delle matrici in C++.

• Una matrice è un array di array:

int a[5][4];

il primo (5) è l’indice delle righe, il secondo (4) è l’indice delle colonne.

• Poiché la matrice è un array l’indice che descrive le righe (e le colonne) assume valori a partire da 0 fino a dimmax-1; quindi la matrice avrà 5 righe, numerate da 0 a 4, e 4 colonne, numerate da 0 a 3.

(10)

Matrici

• La matrice a ha le seguenti componenti:

a[0][0] . . . a[0][3]

a[1][0] . . . a[1][3]

. . .

a[4][0] . . . a[4][3]

• Dopo aver scelto le dimensioni massime per righe e colonne, la matrice può avere n righe ed m colonne, con n ed m compatibili (nell’esempio compatibili con 5 e 4 ).

Matrici

• Per accedere ad un elemento di un array bidimensionale si devono indicare entrambi gli indici:

a[2][1] = 67;

e tali indici devono essere compatibili con la dimensioni dell’array.

• Per acquisire gli elementi di una matrice e per stamparli si deve usare una struttura iterativa per le n righe ed un’altra per le m colonne: gli elementi vengono letti e scritti uno alla volta.

Matrici

//lettura di una matrice i=0,1,.., n-1 k=0, 1, …,m-1 cin>>n>>m; //n<=5, m<=4 for(i=0; i<n; i++)

for(k=0; k<m; k++) cin>>a[i][k];

//lettura di una matrice i=1, 2,...n k=1, 2, …, m cin>>n>>m; //n<=4, m<=3 for(i=1; i<=n; i++)

for(k=1; k<=m; k++) cin>>a[i][k];

Matrici

• Se n=m la matrice si dice quadrata.

• Gli elementi con indice uguale individuano un array che si chiama diagonale della matrice:

diagA = [a11, a22, …, ann]

• Se due matrici A e B hanno lo stesso numero di righe e colonne si può costruire la matrice somma C:

C=A+B cik= aik+ bik

Matrici

• Date due matrici A (n ××× p) e B (p ×× ×× m) se il × numero di colonne di A è uguale al numero di righe di B allora si può definire la matrice C = A ×××× B prodotto “righe ××× colonne”:×

p

cik=

ait· btk t =1

• Consideriamo solo matrici quadrate, quelle maggiormente usate nella matematica.

Matrici

• Una matrice quadrata A possiede n2elementi, quindi difficilmente gli algoritmi su matrici avranno una complessità inferiore a O(n2).

• L’algoritmo per costruire la somma di due matrici è Θ(n2).

• L’algoritmo per costruire il prodotto di matrici, applicando la definizione, è Θ(n3); ne esistono di complessità O(nα) con 2< α < 3.

(11)

Matrici

• L’algoritmo per risolvere il sistema lineare Ax=b (data la matrice A e il vettore b determinare il vettore x) noto come “regola di Cramer” ha complessità O(n!).

• Esistono “metodi diretti” con i quali si trasforma la matrice in una equivalente, per il problema di risolvere il sistema lineare, e che richiedono O(n3) operazioni e “metodi iterativi” che “approssimano” la soluzione in O(n2) operazioni.

Matrici

• L’identità del prodotto tra matrici si chiama matrice identica e viene indicata con I; è una matrice con 1 sulla diagonale e 0 altrove.

• Esercizio. Scrivere un algoritmo per costruire la matrice identica che esegua solo (n2 + n) assegnazioni.

Non eseguire l’ovvio controllo:

se i ≠ k

allora ….0 altrimenti … 1

che porterebbe a n2assegnazioni + n2 confronti

Matrici

• Il prodotto tra matrici non è commutativo:

A ××× B ≠ B ×× ×× A ×

fatta eccezione del caso in cui una delle due sia la matrice I oppure che le due matrici siano uguali.

• La matrice costruita a partire dalla matrice A scambiando le righe con le colonne si chiama matrice trasposta di A, e si indica con AT:

aTik= aki

Matrici

• Una matrice si dice simmetrica se:

aik= aki ∀∀∀∀ i, k

• Se A = AT allora A è simmetrica.

• Due matrici A e B sono uguali se:

aik= bik ∀∀ i, k∀∀

Matrici

• Esercizio.

• Scrivere un algoritmo (efficiente) per verificare se due matrici sono uguali.

• Scrivere un algoritmo (efficiente) per verificare se una matrice è simmetrica.

• Suggerimento: se una proprietà deve essere verificata per ogni elemento, essa è falsa se esiste un solo elemento che non la verifica.

Matrici

• Esercizi per imparare ad usare gli indici delle matrici.

1) date due matrici A(n ××× m) e B(p ×× ××× q) verificare se B è contenuta in A

1 2 3 5 0 -1

A = 4 0 -1 7 B =

3 2 1 4 2 1

B è contenuta invece B1= 1 2 non è contenuta

3 2

(12)

Matrici

2) Dato un cruciverba A(n××××m), matrice di caratteri, e una parola P composta da q caratteri verificare se la parola P sta nel cruciverba per righe o per colonne.

Suggerimento. Verificare che le dimensioni siano compatibili, cercare la prima componente di P se è presente in A ed eseguire la verifica solo se la lunghezza della parola non supera il numero di righe o di colonne che restano da verificare.

Matrici

3) Dati n numeri a1, a2, a3, …, an determinare quanti sono minori a1, quanti minori di a2, di a3, … e in quali posizioni si trovano (per ogni i si deve poter memorizzare un array di indici) e quali sono (per ogni i si deve poter memorizzare un array di valori) .

Array di stringhe

• Per gestire un array di stringhe, poiché le stringhe sono a loro volta degli array, si deve utilizzare una matrice.

• Esempio. Vogliamo memorizzare i nomi degli studenti di questo corso.

• Supponiamo che la stringa che rappresenta il nome e cognome sia memorizzabile in 30 caratteri e che il numero totale degli studenti non superi 190.

Array di stringhe

• Andiamo a definire un array di caratteri dove la prima componente rappresenta il

numero

di studenti e la seconda rappresenta la stringa nome_cognome:

char corsoIEIEN[190][31];

• La componente i-esima corsoIEIEN[i]

rappresenta il nome_cognome dell’i-esimo studente.

Array di stringhe

• Per acquisire gli elementi dell’array si deve utilizzare una struttura iterativa, mentre la stringa viene acquisita come unità:

for(i=0; i<190; i++){

cin>>corsoIEIEN[i];

cout<<corsoIEIEN[i]<<endl;

}

Array di stringhe

• Esercizio.

• Acquisire e stampare dei nomi di persona e successivamente metterli in ordine alfabetico.

Stampare quindi l’elenco ordinato.

• Utilizzare uno dei metodi di ordinamento visti ricordando che il confronto tra stringhe si effettua con la funzione strcmp:

strcmp(corsoIEIEN[i], corsoIEIEN[k]) e che la funzione restituisce un valore positivo,

negativo o nullo.

• Per le assegnazioni usare strcpy.

(13)

Rappresentazione dell’informazione

numerica

Rappresentazione dell’informazione numerica

• Esistono vari tipi di numerazione.

Primitiva: sequenza di simboli tutti uguali;

numerazione nei dadi, carte da gioco, …

Additiva: ogni simbolo ha un valore fisso; si esegue una somma dei valori per determinare il numero; numerazione dei romani, greci, egiziani,…

Rappresentazione dell’informazione numerica

Posizionale: le cifre che compongono la sequenza di simboli che rappresentano il numero hanno un valore che varia con la posizione, si esegue poi la somma; è la numerazione attuale.

• Nella rappresentazione posizionale il numero viene scritto con una notazione del tipo seguente:

N = cncn-1

… c

0. c-1 c-2

… c

-m

Rappresentazione dell’informazione numerica

• Il valore di ogni cifra è:

cifra ×

× × b ×

p

dove b è la base del sistema di numerazione (con b ≠ 0,1) e p è la posizione della cifra.

• Esempio.

3 300 0.03 unità centinaia centesimi

Rappresentazione dell’informazione numerica

• Il valore del numero N viene dalla somma:

N = cnbn+ cn-1bn-1+ … + c0b0+

+ c-1b-1+ …. + c-mb-m

• con ck= 0, 1, 2, …, b-1

• N si ottiene quindi sommando i valori ckbk.

• Formula di rappresentazione dei numeri (per i numeri con infinite cifre dopo la virgola, si ha una serie) (Capitolo 7).

Rappresentazione dell’informazione numerica

• Si possono considerare varie basi.

• b=10 sistema decimale ck= 0, 1, 2,.., 9

• b=2 sistema binario ck= 0, 1

• b=8 sistema ottale ck= 0, 1, 2,.., 7

• b=16 sistema esadecimale

ck= 0, 1, 2,.., 9, A, B, C, D, E, F

• b=60 sistema sessagesimale: si usa per misurare il tempo; non si usano 60 simboli diversi, ma i simboli sono scritti in decimale con due cifre: 00, 01, 02, … 57, 58, 59.

(14)

Rappresentazione dell’informazione numerica

• Cifre delle basi 2, 10, 8 , 16

b=2 b=10 b=8 b=16 4 bit

0 0 0 0 0000

1 1 1 1 0001

2 2 2 0010

3 3 3 0011

4 4 4 0100

5 5 5 0101

6 6 6 0110

7 7 7 0111

8 8 1000

Rappresentazione dell’informazione numerica

b=2 b=10 b=8 b=16 4bit

9 9 1001

(10) A 1010 (11) B 1011 (12) C 1100 (13) D 1101 (14) E 1110 (15) F 1111

• Per scrivere in base 2 i numeri della base 16 = 24 occorrono 4 bit.

Cambi di base

• Passaggio da base b a base 10.

• Il numero è scritto con le cifre della base b: si rappresentano le cifre nella base 10 e si fanno i calcoli in base 10.

• Esempio. b=2

a) 1102= 1××××22 + 1××××21 + 0××××20 = 4 + 2 = 610 b) 112= 1×××2× 1 + 1×××2× 0 = 2 + 1 = 310 c) 11002= 1××××23 + 1××××22 + 0××××21+ 0×××2× 0 =

= 8 + 4 = 1210

Cambi di base

• Le regole per la base 10 valgono anche nelle altre basi:

- spostare la virgola a destra o aggiungere uno zero destra vuole dire “moltiplicare” per la base: b) → a) e a) → c)

- spostare la virgola a sinistra o togliere uno zero sinistra vuole dire “dividere” per la base:

a) → b) e c) → a) .

Cambi di base

• Esempio. b=7

1527= 1 ××××72+ 5 ×××7× 1+ 2 ××××70

= 49 + 35+ 2 = 8610

257 = 2 ×××7× 1+ 5 ××××70 = 14 + 5 = 1910

• Esempio. b=5

4445= 4 ×××5× 2+ 4 ××××51+ 4 ××××50=

= 4 ××××25 + 20 + 4 = 100 + 24 = 12410

Cambi di base

• Esempio. b=8

20.48= 2 ××××81+ 0 ××××80 + 4 ××××8-1 =

= 16 + 0 + 4/8 = 16.510

• Esempio. b=16

AF.C16= 10 ×××16× 1+ 15 ××××160+ 12 ×××16× -1=

= 160 + 15 + 12/16 =

= 175 + 3/4 = 175.7510

(15)

Cambi di base

• Esempio. b=16

30B.A16= 3 ××××162+ 0××××161+ 11××××160+ 10 ×××16× -1

= 3 ××××256 + 0 + 11 + 10/16 =

= 768 + 11 + 0.625 =

= 779.62510

• Si scrivono le cifre del numero nella base 10 (che per b<10 coincidono con quelle della base 10) e anche la base b (in base 10) e si fanno i calcoli in base 10.

Cambi di base

• Passaggio da base 10 a base b.

• Se sapessimo fare con disinvoltura i conti nella base b potremmo scrivere le cifre in base b ed eseguire i conti in base b in maniera analoga.

• Per poter fare sempre i conti in base 10 usiamo la seguente regola: consideriamo il numero suddiviso nella sua parte intera e parte frazionaria

PI . PF = cncn-1… c0 . c-1 c-2 … c-m

Cambi di base

PI : si divide PI e i successivi quozienti per la base e si prendono i resti

PF : si moltiplica PF e le successive parti frazionarie per la base si prendono le parti intere.

• Sia N10= c3 c2 c1 c0 . c-1 c-2c-3 in base b; noi vogliamo trovare le cifre ck.

PI = c3b3+ c2b2+ c1b1+ c0b0=

= b (c3b2+ c2b1+ c1 b0) + c0 // b0=1 dividendo per b si ottiene:

c3b2+ c2b1+ c1 quoziente e c0 è il resto

Cambi di base

si prosegue con il quoziente trovato:

c3b2+ c2b1+ c1 = b (c3b1+ c2) + c1 dividendo per b c1 è il resto c3b + c2= b (c3) + c2 c2 è il resto c3= b·0 + c3 c3 è il resto

(quoziente = 0 perché c3< b)

• Abbiamo estratto nell’ordine c0, c1, c2, c3 che andranno scritti:

c3c2c1c0.

Cambi di base

PF = c-1b-1+ c-2b-2+ c-3b-3 = (finita)

= b-1(c-1 + c-2b-1+ c-3b-2) moltiplicando per b si ottiene:

b·b-1(c-1 + c-2b-1+ c-3b-2) =

= c-1 + c-2b-1+ c-3b-2 c-1 è la parte intera

c-2b-1+ c-3b-2 la parte frazionaria

Cambi di base

si prosegue con la parte frazionaria trovata:

c-2b-1+ c-3b-2 = b-1(c-2 + c-3b-1) c-2 è la parte intera moltiplicando per b

b· c-3b-1 = c-3 c-3 è la parte intera

• Abbiamo estratto nell’ordine c-1, c-2, c-3 che andranno scritti:

. c-1c-2c-3

(16)

Cambi di base

• Esempi.

22710= ? 2 1 1 1 0 0 0 1 1 2

resti

227 2

113 1 56 1

28 0

14 0

7 0

3 1

1 1

0 1

Verifica: 27+ 26+ 25+ 21+ 20= = 128 + 64 + 32 + 2 + 1 = = 227

Cambi di base

• Esempi. 13610= ? 2 1 0 0 0 1 0 0 0 2 resti 136 2

68 0 34 0

17 0

8 1

4 0

2 0

1 0

0 1

Verifica: 27+ 23 = = 128 + 8 = 136

Cambi di base

• Esempi. 0.7510= ? 2 0 . 1 1 2 0.75 ××× 2× parte intera 1.5 : 0.5 ×××× 2 1

1.0 1

la parte frazionaria è 0 Verifica: 1 /2 + 1 /4 = 3 / 4 = = 0.75

Cambi di base

• Esempi. 0.410= ? 2 0 . 0 1 1 0 2 0.4 ×××× 2 parte intera 0.8 : 0.8 ×××× 2 0

1.6 : 0.6 ××× 2 × 1 1.2 : 0.2 ××× 2 × 1 0.4 : 0.4 ××× 2 0×

0.8 …. le parti frazionarie si ripetono: c’è un periodo: 0110 Verifica: 1 / 4 + 1 /8 + 1 / 64 + … = = ? il numero è approssimato

Cambi di base

• Esempi. 0.110= ? 2 0 . 0 0 0 1 1 2 0.1 ×××× 2 parte intera 0.2 : 0.2 ×××× 2 0

0.4 : 0.4 ×××× 2 0 0.8 : 0.8 ×××× 2 0 1.6 : 0.6 ×××× 2 1

1.2 : 0.2 ×××× 2 1 0.4 …. periodo è 0011

0.1 è periodico in base 2

Numeri frazionari

periodici

(17)

Numeri frazionari periodici

• Abbiamo visto che 0.110 = 0.0 00112

• Consideriamo un numero razionale:

p/q con p e q naturali e primi fra loro e q≠0 Eseguendo la divisione

p : q = …

si può ottenere una rappresentazione finita oppure infinita e periodica della parte frazionaria.

a) Se i fattori primi di q sono solo quelli della base, allora la rappresentazione è finita.

Numeri frazionari periodici

b) Se tra i fattori primi di q ci sono fattori diversi dai fattori della base, allora la rappresentazione è infinita e periodica.

• Vediamo per la base b = 10 = 2····5

• Caso a) q = 2k· 5h

sia n = max(h, k); allora si può scrivere p m con m naturale q = 10n m = cscs-1…. c1c0

Numeri frazionari periodici

• Spostando la virgola di n posti verso sinistra a partire da c0si trova la rappresentazione finita, perché finito è il numero di cifre di m.

• Esempio.

31 / 20 = 31 / (22· 5 ) = (31 · 5)/ (22· 52) =

= 155 / 102 = 1.55

7 / 25 = 7 / 52 = (7 · 22)/ (22· 52) =

= 28 / 102 = 0.28

Numeri frazionari periodici

• Caso b) q = ak· bh con a e b anche diversi da 2 e 5; ne segue che non si potrà scrivere q come potenza di 10.

Quando si esegue la divisione:

p = q k1+ k2 0 ≤ k2< q

se le cifre di p sono terminate si “abbassa lo 0”

e si prosegue con la divisione. Il resto k2, variando in un intervallo limitato, ad un certo punto si ripete: si ha pertanto il periodo.

Numeri frazionari periodici

• Esempio.

10 / 3 10 : 3 = 3. 3 3 3 …..

10

1 1 ….. periodo 5 / 7 5 : 7 = 0.714285 714……

50 10

30 20

60 40

5 ….. periodo

Numeri frazionari periodici

• Un numero periodico in base 10 (ci sono fattori diversi da 2 e 5) è anche periodico in base 2.

• Un numero non periodico in base 10 può essere periodico in base 2 (ad esempio 0.1, 0.4).

• I numeri irrazionali, i reali che non si possono scrivere come quoziente di due interi, hanno una rappresentazione infinita e non periodica.

(18)

Passaggi 2   2  

n

• 2n→2 : si espandono le cifre della base 2n in gruppi di n bit 16 = 24→ 2

• 2 →2n : si raggruppano le cifre della base 2 n a n 2 = 2 → 24

• Esempio.

A91.216 = ? 2 = ? 8

A 9 1 . 2 base 16

1010 1001 0001 . 0010 base 2

5 2 2 1 . 1 base 8

Passaggi 2   2  

n

• Esempio.

2E0.FC16 = ? 2 = ? 8

2 E 0 . F C base 16

0010 1110 0000 . 1111 1100 base 2

1 3 4 0 . 7 7 base 8

Operazioni in base 2

Operazioni in base 2

Addizione.

0 + 0 = 0 1 + 0 = 0 + 1 = 1 1 + 1 = 1(riporto) 0

Esempio.

1 5 + 5 21 0

1 1 1 1 + 1 0 1 1 0 11 10 10

Operazioni in base 2

Sottrazione.

0 - 0 = 0 1 - 0 = 1 0 - 1 = 1(prestito)0 - 1 = 1 Esempio.

210 - 5 1 5

11 01 11 01 0 - 0 1 0 1 0 1 1 1 1

Esercizio

• Esercizio.

• Risolvere l’equazione 231x= 4510

vale a dire: determinare la base x in modo da soddisfare l’uguaglianza.

• Soluzione. Utilizzando la formula di rappresentazione dei numeri abbiamo:

2 ⋅⋅⋅⋅ x2+ 3 ⋅⋅⋅⋅ x1+ 1 = 45

2x2+ 3x - 44 = 0 x1= -11/2 x2=4 Pertanto la soluzione è: x = 4.

Verifica: 2 ⋅⋅⋅⋅ 16 + 3 ⋅⋅⋅⋅ 4 + 1 = 32 + 12 + 1 = 45

(19)

Esercizio

• Esercizio.

• Un matematico incontra un extraterrestre e gli pone il problema di trovare le soluzioni della seguente equazione:

x2- 13x + 36 = 0

L’extraterrestre dice che le soluzioni sono: 5 e 6.

Quante dita ha l’extraterrestre?

Esercizio

• Soluzione.

• La base 10 corrisponde al numero delle nostre dita. Per l’extraterrestre i numeri 1, 13, 36 sono nella base b che corrisponde al numero delle sue dita.

Poiché la risposta è 5 e 6, che sono anche numeri della base 10, ricordando

x2– s x + p = 0 s = 11 e p = 30 si ha:

13b= 1110 36b= 3010 e pertanto b=8.

Soluzione esercizio

Soluzione esercizio

Caso n = 0 .

i = 0, quindi il predicato “mentre i ≠ 0 …” è falso: il ciclo non viene eseguito.

• Caso n < 0 .

se a < b il ciclo non termina: a diminuisce e quindi rimane minore di b

se a = b il ciclo non termina: entrambi crescono di 1

se a > b il ciclo termina: continua diventa falso.

Soluzione esercizio

Caso n > 0 .

Caso a < b .

Viene eseguita l’istruzione a ← a-1, quindi è ancora a < b; il ciclo termina quando i = n; il numero di operazioni è:

2ta + (n+1) tp + nta + ntc + nta ⇒⇒⇒⇒ c·n

continua i a<b a i←

b non varia, a diventa a-n

Soluzione esercizio

Caso a > b .

Viene eseguita l’istruzione continua ← falso, quindi il ciclo termina; il numero di operazioni è:

2ta + tp + ta + tc + tc + ta+ tp⇒⇒⇒⇒ costante

continua← i← a<b a = b continua←

i←

b non varia, a non varia

(20)

Soluzione esercizio

Caso a = b.

Vengono eseguite le istruzioni a←a+1 e b←b+1; il ciclo interno viene eseguito n volte e il ciclo esterno termina quando i = n; il numero di operazioni è:

2ta + (n+1) tp + nta + ntc + n tc + n(n+1) tp+

continua← i← a<b a=b i←

+ 2 n2ta ⇒ c·n 2

a←

b←

a diventa a + n2 , b diventa b + n2

Riferimenti

Documenti correlati

I: il valore di ciascun elemento dello array bidimensionale Pi: il numero degli elementi da inserire non può essere maggiore della cardinalità dell’array. U: l’array

Scrivere un metodo ricorsivo che, dato un array a di interi, restituisce la somma al- ternante di a, ovvero il valore ottenuto aggiungendo gli elementi di a in posizione pari

Prima di chiamare la free sull'array chiamarla su ogni

– Soluzione: si passa alla funzione un ulteriore parametro di tipo array, che viene “riempito” con il risultato.. E i parametri di

● Se gli estremi degli scaglioni e/o le percentuali cambiano, devo cambiare solo l'array e non il programma che fa la ricerca!.. Algoritmi su

Quindi main individua, chiamando un’altra funzione, la colonna di A avente il massimo numero di elementi dispari (se ce ne sono più di una, si prende la prima incontrata)..

Alla fine dei confronti l’elemento nella prima posizione risulta sicuramente minore di tutti gli elementi nelle posizioni successive.. Successivamente si ripete il

¨  L’espressione a[i] restituisce il valore della variabile con indice i, quindi il tipo di questa espressione è il tipo base dell'array. Accesso agli elementi di