















Studia grazie alle numerose risorse presenti su Docsity
Guadagna punti aiutando altri studenti oppure acquistali con un piano Premium
Prepara i tuoi esami
Studia grazie alle numerose risorse presenti su Docsity
Prepara i tuoi esami con i documenti condivisi da studenti come te su Docsity
Trova i documenti specifici per gli esami della tua università
Preparati con lezioni e prove svolte basate sui programmi universitari!
Rispondi a reali domande d’esame e scopri la tua preparazione
Riassumi i tuoi documenti, fagli domande, convertili in quiz e mappe concettuali
Studia con prove svolte, tesine e consigli utili
Togliti ogni dubbio leggendo le risposte alle domande fatte da altri studenti come te
Esplora i documenti più scaricati per gli argomenti di studio più popolari
Ottieni i punti per scaricare
Guadagna punti aiutando altri studenti oppure acquistali con un piano Premium
Le operazioni di ingresso e uscita in un agente di calcolo e descrive due algoritmi di ricerca: sequenziale e binaria. La ricerca sequenziale esegue una serie di confronti consecutivi, mentre l'algoritmo binario ristra la ricerca a metà dell'elenco. Il documento include anche un'analisi del lavoro totale svolto da entrambi gli algoritmi e una comparazione tra di essi.
Tipologia: Prove d'esame
1 / 23
Questa pagina non è visibile nell’anteprima
Non perderti parti importanti!
















INFORMATICA: Preparazione all'Esame L'Informatica è lo studio degli algoritmi , che comprende: _ le loro proprietà formali e matematiche; _ le loro implementazioni hardware; _ le loro implementazioni logistiche; _ le loro applicazioni. Esistono tre tipi di categorie che racchiudono le operazioni utili alla realizzazione degli algoritmi:
Un algoritmo deve produrre un risultato e terminare in un tempo finito. L'informatica è lo studio degli algoritmi, che comprende: _ le loro proprietà formali e matematiche _ le loro implementazioni hardware _ le loro implementazioni linguistiche _ le loro applicazioni Cap. 2 IDEAZIONE E PROGETTO DI ALGORITMI Una possibilità di rappresentare gli algoritmi è l'uso del linguaggio naturale, con cui abbiamo maggiore familiarità. Il linguaggio naturale può essere estremamente prolisso, determinando algoritmi incoerenti. Il linguaggio naturale è troppo 'ricco' in termini di interpretazioni e significato. Poiché le lingue naturali non sono sufficientemente precise per gli algoritmi, si potrebbe cedere alla tentazione di passare all'estremo opposto --> linguaggio di programmazione di alto livello. Se i due estremi rappresentati dai linguaggi naturali e dai linguaggi di programmazione di alto livello sono inadatti, cosa si dovrebbe usare? Lo pseudo codice comprende costrutti in italiano studiati per assomigliare alle istruzioni di un linguaggio di programmazione, ma che in realtà non si eseguono su un computer. Lo pseudo codice rappresenta un compromesso tra i due estremi del linguaggio naturale e di quello formale; è semplice, leggibile e privo di regole grammaticali. OPERAZIONI SEQUENZIALI Lo pseudo codice deve comprendere le istruzioni necessarie a eseguire le tre operazioni sequenziali di base: calcolo, ingresso e uscita. Una variabile è una posizione di memoria con nome, che contiene un valore. In pseudo codice non ha importanza l'esatto modo in cui si sceglie di scrivere le istruzioni, purché queste siano chiare, effettivamente calcolabili e non ambigue. Si tratta di una notazione elastica che può essere adattata secondo la propria visione di come esprimere al meglio idee e algoritmi.
Le operazioni di ingresso inviano valori di dati dal mondo esterno all'agente di calcolo, che può quindi utilizzarli nelle istruzioni successive. Le operazioni di uscita inviano i risultati dall'agente di calcolo al mondo esterno. Se l'agente di calcolo è un computer, le comunicazioni con il mondo esterno vengono svolte tramite i dispositivi ingresso/uscita disponibili su un sistema tipico. Le istruzioni di ingresso e uscita in pseudo codice sono espresse così: Ingresso Ottieni i valori per "variabile", "variabile", ... Uscita Stampa i valori di "variabile", "variabile", ... Quando l'algoritmo raggiunge questa operazione di ingresso, attende finché qualcuno o qualcosa fornisce un valore per la variabile. Quando ha ricevuto e memorizzato un valore per la variabile, l'algoritmo continua con l'istruzione successiva. L'istruzione "stampa" indica di visualizzare il valore al mondo esterno, mostrandolo sullo schermo. Mediante le tre operazioni sequenziali - calcolo, ingresso e uscita - è possibile scrivere degli algoritmi semplici. OPERAZIONI CONDIZIONALI E ITERATIVE L'algoritmo precedente esegue una serie di operazioni una volta sola, quindi si ferma. Un algoritmo puramente sequenziale viene talvolta definito algoritmo lineare perché esegue le istruzioni in linea retta dall'alto al basso e quindi si ferma. Per poter eseguire ramificazioni e ripetizioni, lo pseudo codice richiede istruzioni supplementari per l'implementazione di operazioni condizionali e iterative --> operazioni di controllo. Le istruzioni condizionali sono operazioni che "pongono domande". Consentono all'algoritmo di porre una domanda e di selezionare, in base alla risposta fornita, l'operazione successiva da eseguire. L'istruzione condizionale più comune è if/then/else che presenta il formato seguente: Se "una condizione vera/falsa" è vera allora prima serie di operazioni algoritmiche Altrimenti seconda serie di operazioni algoritmiche Questa istruzione ha il seguente significato:
100° passaggio attraverso il ciclo, il valore di conteggio viene incrementato. Quando la condizione di continuazione risulta falsa il ciclo si conclude. Questo ciclo è chiamato ciclo a valutazione anticipata perché la condizione di continuazione viene valutata all'inizio di ciascuna iterazione attraverso il ciclo e pertanto è possibile che il corpo del ciclo non venga mai eseguito. Questo fatto può causare dei problemi. Nella tabella precedente si chiede all'utente se desidera eseguire nuovamente il calcolo, ma la domanda è posta soltanto alla fine dell'esecuzione del corpo del ciclo --> per questo bisogna fornire alla variabile risposta un valore fittizio 'sì'. Un'altra variante della struttura di ciclo è il ciclo a valutazione posticipata; anch'esso utilizza la condizione di continuazione vero/falso per il controllo dell'esecuzione, tuttavia il test viene eseguito alla fine del corpo del ciclo e non all'inizio. Il ciclo viene espresso mediante l'istruzione Ripeti/ Finché. Questa struttura esegue tutte le operazioni algoritmiche contenute nel corpo del ciclo prima della valutazione della condizione vera/falsa specificata alla fine. Se questa condizione è falsa, il ciclo termina e l'esecuzione continua con l'operazione successiva. Se invece è vera, l'intero corpo del ciclo viene eseguito nuovamente. Nella variante Ripeti/Finché, il corpo del ciclo viene sempre eseguito almeno una volta, mente il ciclo Finché può essere eseguito 0, 1 o più volte. Queste operazioni rappresentano le primitive dell'agente di calcolo. Si tratta delle istruzioni che si presume vengano comprese dall'agente di calcolo e che questo deve essere in grado di eseguire senza ulteriori spiegazioni o semplificazioni. Esempi di risoluzione dei problemi algoritmici --> vedi libro da pag.51 a pag. Passo Operazione 1 Risposta = si 2 Finché (risposta = si) ripeti i passaggi da 3 a 11 3 Ottieni i valori per galloni usati, miglia iniziali, miglia finali 4 Imposta il valore di distanza percorsa a (miglia finali - miglia iniziali) 5 Imposta il valore di miglia medie per gallone a (distanza percorsa + galloni usati) 6 Stampa il valore di miglia medie per gallone 7 Se miglia medie per gallone è maggiore di 25.0 allora 8 Stampa il messaggio 'Stai viaggiando con un consumo accettabile' ALTRIMENTI 9 Stampa il messaggio 'Stai viaggiando con un consumo NON accettabile' 10 Stampa il messaggio 'Vuoi fare un altro calcolo? Inserisci Sì o No' 11 Ottieni un nuovo valore per risposta dall'utente 12 Stop
Cap. 3 EFFICIENZA DEGLI ALGORITMI La prima e fondamentale caratteristica degli algoritmi è la correttezza. Un algoritmo creato per risolvere un problema deve, per definizione, fornire un risultato e fermarsi. Il risultato deve essere una soluzione corretta del problema. Determinare che un algoritmo fornisca risultati corretti non è facile come sembra. Da un lato, l'algoritmo potrebbe fornire risultati corretti, ma al problema errato; ciò può accadere quando si progetta un algoritmo senza una completa comprensione del problema che si vuole risolvere. Inoltre, una volta compreso il problema, l'algoritmo deve fornire risultati corretti per tutti i possibili valori di ingresso, non solo per i valori più comuni. Conta anche la precisione del risultato che intendiamo accettare come corretta. La manutenzione dei programmi richiede tempo e denaro. La persona che deve modificare un programma spesso non è la stessa che ha scritto il programma originale. Per facilitare la manutenzione, l'algoritmo utilizzato dal programma deve essere facile da capire. La facilità di comprensione, la chiarezza, la facilità di gestione è una caratteristica desiderabile di un algoritmo. L'eleganza per gli algoritmi corrisponde alla linea o allo stile delle automobili. Talvolta eleganza e facilità di comprensione vanno in direzioni contrarie: più elegante è la soluzione, più difficile risulta da capire. Efficienza è il termine usato per descrivere l'uso attento delle risorse da parte di un algoritmo, e insieme a correttezza, facilità di comprensione ed eleganza, è una delle caratteristiche desiderabili di un algoritmo. La valutazione del tempo di esecuzione di un algoritmo tende a riflettere maggiormente la velocità della macchina o le variazioni nei dati di ingresso, che l'efficienza dell'algoritmo stesso. Utilizzando la stessa macchina e lo stesso elenco di nomi, ma cercando nomi diversi, si ottiene un'indicazione dell'impatto che la scelta del nome ha sul tempo di esecuzione dell'algoritmo su quella particolare macchina --> benchmarking. Questi sono utili per classificare una macchina rispetto a un'altra e per determinare la sensibilità di un particolare algoritmo rispetto a variazioni nei dati di ingresso su una particolare macchina. Lo studio dell'efficienza degli algoritmi si chiama analisi degli algoritmi.
Per quanto riguarda l'efficienza dell'ordinamento di selezione rispetto allo spazio, l'elenco di partenza occupa n locazioni di memoria. Serve ancora un po' di spazio per il marcatore tra le sezioni non ordinata e ordinata, e per registrare il valore massimo temporaneo e la sua posizione nell'elenco. Se i due numeri da scambiare si trovano nelle posizioni X e Y nell'elenco, potremmo pensare di scambiarli con i due passi seguenti.
L'algoritmo di ricerca sequenziale cerca un elemento particolare in un elenco di n elementi; è un algoritmo (c)n. L'algoritmo di ricerca binaria è più efficiente, ma funziona soltanto quando l'elenco è già ordinato. L'algoritmo di ricerca binaria opera in modo simile su un elenco ordinato. Prima cerca NOME verso la metà dell'elenco: se il nome che trova coincide con NOME, la ricerca è finita. Se NOME precede alfabeticamente il nome che si trova a metà dell'elenco, la ricerca viene ristretta alla prima metà dell'elenco stesso e la procedura viene ripetuta su questo elenco più piccolo.
Nella tabella è riportata una versione in pseudo codice dell'algoritmo di ricerca binaria su un elenco ordinato di n elementi. Le etichette inizio e fine indicano l'inizio e la fine della sezione dell'elenco attualmente considerata. Inizialmente viene considerato l'interno elenco, perciò inizio è 1 e fine è n. Se NOME non viene trovato al punto centrale m della sezione attuale dell'elenco, allora impostare fine uguale a 1 meno il punto centrale significa che, alla successiva iterazione del ciclo, la ricerca verrà effettuata nella prima metà della sezione corrente; impostare inizio uguale a 1 più il punto centrale significa invece che alla successiva iterazione del ciclo la ricerca verrà effettuata nella seconda metà della sezione corrente. Perciò, al procedere dell'algoritmo, il marcatore inizio può spostarsi verso la fine dell'elenco, e il marcatore fine può spostarsi verso l'inizio. Se i marcatori inizio e fine si incrociano, cioè se fine diventa inferiore a inizio, allora la sezione corrente dell'elenco è vuota e la ricerca termina. Come l'algoritmo di ricerca sequenziale, quello di ricerca binaria su a sa anch'esso su confronti, perciò al fine di analizzarlo contiamo il numero di confronti come indicazione del lavoro fatto. Il caso migliore, come nella ricerca sequenziale, richiede un solo confronto: NOME viene trovato al primo tentativo. Il caso peggiore si verifica quando NOME non nel'elenco; tuttavia, nella ricerca binaria questo fatto viene rilevato molto prima, rispetto alla ricerca sequenziale. Il numero di volte per cui un numero n può essere tagliato a metà senza scendere sotto 1 si chiama logaritmo di n in base 2 e si scrive lg n. Supponiamo di eseguire una ricerca binaria su n nomi. Nel caso peggiore il numero di confronti è legato al numero di volte per cui si può dimezzare l'elenco di lunghezza n. Gli algoritmi di ricerca binaria e di ricerca sequenziale risolvono entrambi il problema della ricerca nell'elenco telefonico, ma differiscono per l'ordine di grandezza del lavoro svolto. La ricerca binaria è un algoritmo (c)lg n, mentre la ricerca sequenziale è (c)n, sia nel caso peggiore, sia nel caso medio. Per confrontare questi due algoritmi, supponiamo che vi siano 100 elementi nell'elenco. Nel caso peggiore, la ricerca sequenziale richiede 100 confronti, la ricerca binaria 7(2°7=128). Nel caso medio, la ricerca sequenziale richiede circa 50 confronti, quella binaria 6 o 7. Il miglioramento nella ricerca binaria risulta ancora più evidente al crescere della dimensione dell'elenco. La ricerca binaria funziona soltanto su un elenco già ordinato. Un elenco non ordinato può essere ordinato usando una ricerca binaria, ma l'ordinamento in sé richiede parecchio lavoro. Se si ha Ottieni i valori per NOME, n, N1.....Nn e T..... Tn 2 Imposta il valore di Inizio a 1 e il valore di Trovato a NO 3 Imposta il valore di fine a n 4 Finché Trovato=NO e inizio è minore o uguale a fine esegui i passi da 5 a 10 5 Imposta il valore di m al valore di posto centrale tra inizio e fine 6 Se NOME è uguale a Nm il nome trovato al punto centrale tra inizio e fine, allora esegui i passi 7 e 8 7 Stampa il numero telefonico della persona trovata Tm 8 Imposta il valore di Trovato a SI 9 Altrimenti se NOME precede Nm nel l'ordinamento alfabetico, allora imposta fine= m- 1 10 Altrimenti (NOME segue Nm nel l'ordinamento alfabetico) imposta inizio = m + 1 11 Se (Trovato = NO) allora stampa il messaggio 'Spiacente, il nome cercato non è nell'elenco' 12 Stop
Il valore assoluto, tuttavia, è 0000...0000. Perciò questa configurazione di bit rappresenta la quantità numerica "zero negativo", un valore che non possiede alcun significato matematico reale e non dovrebbe avere una rappresentazione distinta dall'altra rappresentazione dello zero, 0000...0000. L'esistenza di due configurazioni di bit distinte per la stessa quantità numerica determina notevoli complicazioni dal punto di vista progettuale. I progettisti di computer tendono a favorire le rappresentazioni di interi con segno che non presentino il problema dei due zeri. Una tra le più comuni è la rappresentazione in complemento a due. Nella rappresentazione in complemento a due è presente un singolo zero, il numero binario 000...0. Tuttavia, l'esistenza di una singola configurazione per lo zero porta a un'altra situazione insolita: il numero totale di valori che può essere rappresentato con n bit è 2°n. _ numeri frazionari I numeri frazionari possono anch'essi essere rappresentati in binario utilizzando le tecniche di intero con segno appena descritte. Per fare ciò, tuttavia, occorre prima convertire il numero in notazione scientifica. M è la mantissa, B è la base dell'esponente ed E è l'esponente. Sia la mantissa, sia l'esponente sono numeri interi con segno, perciò è possibile utilizzare la notazione segno e valore assoluto o quella in complemento a due appena descritte per rappresentare ciascuno di questi due campi. In binario, il valore 5 è 101. _ Informazioni testuali Per rappresentare dati testuali in binario, il sistema assegna a ciascuna lettera o simbolo stampabile dell'alfabeto un numero univoco, quindi memorizza internamente tale simbolo usando l'equivalente binario del numero. Qui sopra è indicato che la quantità numerica a 8 bit 10000001 viene interpretata come carattere "!". Tuttavia, l'unico modo con cui il computer riesce a capire che il valore a 8 bit 10000001 rappresenta il simbolo "!" e non il valore intero senza segno 129 o il valore intero con segno -1 è dato dal contesto in cui il valore è utilizzato. Per agevolare lo scambio di informazioni testuali tra sistemi informatici sarebbe utile che tutti utilizzassero la stessa mappatura dei codici. Attualmente il codice maggiormente utilizzato per rappresentare i caratteri di un sistema informatico è denominato ASCII, acronimo per American Simbolo Valore decimale Binario (usando 8 cifre binarie) A 1. B 2. C 3. D 4.
... ... Z 26. @ 128. ! 129. ... ... ...
Standard Code for Information Interchange. Questo standard internazionale utilizza 8 bit per rappresentare ciascun carattere, perciò è in grado di codificare un totale di 2°8 = 256 caratteri diversi. Oggi sta rapidamente guadagnando popolarità un nuovo set di codici denominato UNICODE che utilizza una rappresentazione a 16 bit per i caratteri, invece degli 8 del sistema ASCII. Ciò significa che l'UNICODE è in grado di rappresentare 2°16 = 65536 caratteri univoci. RAPPRESENTAZIONE BINARIA DI SUONI E IMMAGINI Il suono è un'informazione di tipo analogico. In una rappresentazione digitale, i valori di un dato oggetto sono tratti da un insieme finito come lettere o da un sottoinsieme di interi. In una rappresentazione analogica, gli oggetti possono assumere qualsiasi valore. Nel caso del suono, per esempio, una nota è una forma d'onda sinusoidale continua che varia in modo periodico regolare nel tempo. L'ampiezza dell'onda, ovvero l'intervallo compreso tra i valori massimo è minimo che essa può assumere, è una misura della sua intensità sonora: maggiore è l'ampiezza, più forte è il suono. Il periodo dell'onda, indicato come T, è il tempo necessario all'onda stessa per completare un ciclo. La frequenza f è il numero totale di cicli per unità di tempo, misurata in cicli al secondo, o hertz. La frequenza determina l'altezza del suono. Più alta è la frequenza, più alta è la nota percepita. Per memorizzare in un computer una forma d'onda, il segnale analogico deve prima essere digitalizzato, ossia convertito in rappresentazione digitale. Per fare ciò è possibile utilizzare la tecnica del campionamento. A intervalli fissi, l'entità del segnale, ovvero il valore da questo assunto rispetto al valore 0 di riferimento, viene misurata e memorizzata come valore intero. L'onda viene così rappresentata in forma digitale nel computer come sequenza di valori numerici campionati. Ciascun campione così ottenuto deve quindi essere convertito in un valore numerico, intero o reale. Per fare questo si procede con un processo chiamato quantizzazione, che consiste, in modo semplificato, nello stabilire il numero di bit che si intendono assegnare ai campioni, e il tipo di rappresentazione del dato, se intero o reale. Da questi valori digitalizzati il computer può ricreare un' approssimazione dell'onda analogica originale. La precisione con la quale il suono originale può essere riprodotto dipende da due parametri chiave: la frequenza di campionamento e la risoluzione in bit. La frequenza di campionamento misura quante volte al secondo si esegue il campionamento dell'ampiezza dell'onda sonora. Ovviamente, maggiore è la frequenza di campionamento, più precisa è la riproduzione. Maggiore è la frequenza di campionamento, maggiore è l'intervallo di frequenze sonore che può essere catturato se la frequenza di un'onda è maggiore o uguale alla frequenza di campionamento, esiste il rischio teorico di non campionare alcun punto sull'intera forma d'onda. Questa frequenza di campionamento produce un valore di ampiezza costante, deformando completamente il suono originale. La risoluzione è il numero di bit utilizzato per codificare ciascun campione. Oggigiorno sono in suo molti formati di codifica audio, tra cui WAV, AU, QuickTime e RealAudio. Il formato più famoso è MP3. Con MP3 si esegue il campionamento dei segnali audio a una frequenza di 44100 campioni al secondo, usando 16 bit per campione --> suono di alta qualità.
Queste due tecniche sono esempi di schemi di compressione senza perdita. Ciò significa che non si perde alcuna informazione nella compressione ed è possibile riprodurre i dati originali. Gli schemi di compressione con perdita, invece, comprimono i dati in un modo che non garantisce che tutte le informazioni nei dati originali possano essere ricreate completamente. AFFIDABILITÀ DELLA RAPPRESENTAZIONE BINARIA I computer utilizzano la rappresentazione binaria non per motivi teorici, ma per motivi di affidabilità. Con l'invecchiamento i dispositivi elettrici tendono a diventare inaffidabili e potrebbero manifestare devianze o cambiare il loro stato energetico. Il problema della rappresentazione in base 10 è che richiede la memorizzazione di 10 simboli univoci, rendendo perciò necessari dispositivi con 10 stati stabili. Tali dispositivi sono rari. I sistemi elettrici tendono a funzionare in un ambiente bistabile, nel quale vi sono solo due Stati stabili separati da una barriera energetica di notevoli dimensioni. Ciascun transistor contiene tre connettori: due di ingresso e uno di uscita. La prima linea di ingresso, chiamata controllo o base, viene utilizzata per aprire o chiudere l'interruttore all'interno del transistor. In questo stato la tensione proviene dalla linea Ingresso, chiamata collettore, viene trasferita direttamente alla linea Uscita, chiamata emettitore, e questa tensione può essere rilevata mediante un dispositivo di misura. Lo stato OFF può essere utilizzato per rappresentare il valore binario 0. LOGICA BOOLEANA La costruzione dei circuiti del computer si basa sul ramo della matematica e della logica simbolica denominato logica booleana. Quest'area tratta le regole di manipolazione dei due valori logici vero (true) e falso (false). È facile vedere la relazione tra la logica booleana e la progettazione di un computer: il valore vero può rappresentare il valore binario 1 e il valore falso può rappresentare il valore binario 0. Definiamo un'espressione booleana come qualsiasi espressione che dà come risultato vero o falso. Nella logica booleana, le operazioni utilizzate per costruire le espressioni booleane sono AND, OR e NOT. La regola per eseguire le operazioni AND è la seguente: se a e b sono espressioni booleane, il valore dell'espressione (a AND b), scritta anche come (a. b), è vero se e solo se a e b hanno valore vero; altrimenti, l'espressione ha il valore falso. Questa regola afferma che l'operazione AND produce il valore vero se e solo se entrambi i suoi operandi sono veri. Tabella di verità: La seconda operazione booleana è OR. La regola è la seguente: se a e b sono espressioni booleane, il valore dell'espressione booleana (a OR b), scritta anche come (a+b), è vero se a è vero, se b è vero o se entrambi sono veri. Altrimenti, (a OR b) ha il valore falso. Ingressi Uscita a b a AND b (scritto anche a. b) Falso Falso Falso Falso VERO Falso VERO FALSO Falso VERO VERO Vero
Tabella di verità: L'ultimo operatore booleano è NOT. Diversamente da AND e OR, che richiedono due operandi e sono pertanto chiamati operatori binari, NOT richiede soltanto un operando ed è un operatore unario. La regola di valutazione dell'operazione NOT è la seguente: se a è un'espressione booleana, il valore dell'espressione (NOT a), scritta anche come ä, è vero se a ha il valore falso ed è falso se a ha il valore vero. Tabella di verità: In modo informale si dice che l'operazione NOT inverte o complementa il valore di un'espressione booleana, rendendola Vera se è falsa e viceversa. Ingressi Uscita a b a OR b (scritto anche a + b) Falso Falso Falso Falso VERO Vero VERO FALSO Vero VERO VERO Vero Ingressi Uscita a NOT a (scritto anche ä) Falso VERO VERO FALSO
Per realizzare una porta OR, si inizia nuovamente con due transistor. Tuttavia, questa volta essi vengono connessi in parallelo invece che in serie. Se Controllo 1 o Controllo 2 sono impostati a 1, il transistor corrispondente si trova nello stato ON e la corrente produce un valore di uscita 0. Solo se entrambe le linee di controllo sono 0, chiudendo entrambi i transistor, la linea di uscita contiene
sue N linee di ingresso, quindi inviare un segnale (ossia 1) sulla singola linea di uscita che ha tale numero identificativo. Tutte le altre linee di uscita sono impostare a 0. Insieme, i circuiti decodificatore e multiplexer consentono di realizzare computer che eseguono le istruzioni corrette usando i valori di dati corretti. Mentre un circuito decodificatore può essere utilizzato per selezionare l'istruzione corretta, un multiplexer può aiutare ad assicurare che il computer esegua questa istruzione con i dati corretti. Cap. 8 'IL SOFTWARE' I linguaggi di programmazione di alto livello sono stati creati per superare questi problemi. Perciò, da un programma scritto in un linguaggio di alto livello ci aspettiamo che: _ il programmatore non debba occuparsi dei dettagli circa lo spostamento degli elementi di dati in memoria, o il punto esatto in cui tali elementi sono registrati; _ il programmatore possa osservare le attività da un punto di vista macroscopico, ragionando a un livello più alto di risoluzione dei problemi; _ i programmi siano portabili e non specifici della macchina; _ le istruzioni di programmazione siano più vicine al linguaggio naturale e utilizzino la notazione matematica standard. I linguaggi di programmazione di alto livello sono spesso detti linguaggi di terza generazione. Questo livello di astrazione più alto comporta un prezzo da pagare: quando siamo passati dal linguaggio macchina al linguaggio assemblativo, ci è servito un componente del software di sistema, un assemblatore, per tradurre le istruzioni del linguaggio assemblativo in linguaggio macchina. Il software di sistema corrispondente si chiama compilatore. Invece di tradurre direttamente in codice oggetto, spesso il compilatore traduce le istruzioni di alto livello in un codice di basso livello abbastanza vicino al linguaggio macchina, lasciando il passaggio finale a un altro traduttore. Un programma può richiedere una copia di tale codice oggetto, per includerla nel proprio. Un componente del software di sistema detto linker inserisce il codice oggetto richiesto dalle librerie di codice nel codice oggetto del programma richiedente. Potrebbe sembrare che, se tutti i programmi per computer fossero scritti nello stesso linguaggio di programmazione, tutto sarebbe più semplice. In realtà, esistono più linguaggi di programmazione non tanto perché alcuni compiti possono essere eseguiti da uno e non dall'altro, ma perché ogni linguaggio è progettato per soddisfare esigenze specifiche. Il principale motivo che ha portato alla moltiplicazione dei linguaggi di programmazione è la proliferazione delle attività di programmazione. LINGUAGGI PROCEDURALI Un programma scritto in un linguaggio procedurale è costituito da sequenze di istruzioni che elaborano dati, accedono alla memoria e trasferiscono informazioni da e verso i dispositivi periferici. I linguaggi procedurali derivano direttamente dall'architettura di Von Neumann, caratterizzata da cicli sequenziali prelievo-decodifica-esecuzione. Questa architettura, nella quale la memoria è punto di partenza ed arrivo del ciclo di esecuzione delle istruzioni e dei dati su cui esse operano, giustifica la progettazione di un linguaggio in cui le operazioni di base siamo la lettura e la scrittura di dati. I linguaggi procedurali possono differire nel modo in cui le istruzioni devono essere disposte su una riga e nel modo in cui si possono definire i nomi nelle variabili, oltre che nel modo in cui si assegna un nuovo valore a una variabile, nel meccanismo fornito dal linguaggio per il controllo del flusso tramite istruzioni condizionali e cicli, e nelle istruzioni di ingresso e uscita. Tutti i linguaggi procedurali indicano al computer, passo per passo, come manipolare il contenuto dislocazioni di memoria. La gestione della complessità Tra gli aspetti da gestire nella fase di sviluppo del software va considerata la scelta dell'approccio da seguire per prevenire alla soluzione del problema. Nella programmazione procedurale si adotta spesso una metodologia di suddivisione del problema in sottoproblemi.
Un'interfaccia utente grafica con finestre, icone, pulsanti, è un esempio di quanto si può ottenere con la programmazione orientata agli oggetti. LINGUAGGI PER SCOPI SPECIFICI Uno di questi linguaggi specializzati è SQL progettato per essere utilizzato nella definizione, modifica e interrogazione di basi di dati. Un'altra classe di linguaggi adibiti ad usi speciali e che tuttavia non sono linguaggi di programmazione sono i linguaggi di marcatura tra cui si annoverano XML e HTML, molto usati nella creazione di pagine ed applicazioni per il World Wide Web. Entrambi questi linguaggi si basano sul concetto di "marcatore" o tag. Un tag è una particolare stringa di testo compresa tra i caratteri < e > utilizzata per delimitare una porzione di testo e che indica ad un apposito software di interpretazione il tipo di elaborazione da svolgere sul testo delimitato. In HTML l'insieme di tag utilizzabile è fisso. Per consentire la creazione di tag personalizzati è stato sviluppato XML. Le pagine HTML scritte con i soli tag sono immodificabili o statiche. Un linguaggio di scripting è un linguaggio "leggero". JavaScript è un linguaggio di scripting orientato agli oggetti con una sintassi simile a quella di Java, ma molto meno complesso, che possiede oggetti predefiniti i cui metodi sono in grado di manipolare dinamicamente il contenuto, cioè i tag. In questo modo è possibile elaborare i dati inseriti in un modulo di registrazione a un servizio su Internet per verificarne la completezza e correttezza, e avvertire l'utente di completare il modulo nei punti errati o mancanti, impedendo che questi vada oltre nel processo di registrazione al servizio. PARADIGMI DI PROGRAMMAZIONE ALTERNATIVI Un paradigma è un modello o struttura mentale per rappresentare o ragionare su qualche cosa. Il paradigma dei linguaggi di programmazione procedurali dice che al computer è fornita una sequenza di istruzioni dettagliate. Il risultato finale di tutte le manipolazioni delle celle di memoria è la soluzione del problema. La programmazione in un linguaggio procedurale consiste in:
problema può essere molto più alto di quello previsto, e superare il valore delle informazioni prodotte. Al termine dello studio, un documento di fattibilità esprime i risultati, consigliando se procedere con l'acquisto di hardware e software.