Dispensa n.5 INTRODUZIONE Le tecnologie di successo sociale producono strumenti il cui impiego è facilitato dalla presenza di un’interfaccia utente che consente di usare tali strumenti senza doverne conoscere i dettagli di funzionamento: anzi, proprio la facilità d’uso è spesso condizione di tale successo. Imparare ad usare il cellulare implica la necessità di imparare le modalità di utilizzo della sua interfaccia utente: questo però esula completamente dal capire o per lo meno conoscere “cosa c’è dentro” o “come funziona”; d’altro canto, questa non conoscenza non pregiudica la possibilità di una corretta e completa fruizione di questo strumento. La stessa cosa può esser detta per gli strumenti informatici. Ad esempio, molti videogiochi presenti oggi sul mercato non sono altro che “calcolatori dedicati”, cioè sistemi che funzionano grazie ad un calcolatore che risulta però del tutto invisibile agli utenti. Il buon uso di questi strumenti non dipende da competenze tecnologiche e può essere appreso da manuali in cui si spiega le modalità del gioco (pulsante rosso = possibilità di sparare ad astronavi aliene ecc..) senza mai citare termini quali “linguaggio di programmazione”, “microprocessore” o “sistema operativo”. La necessità di avere almeno un po’ di nozioni teoriche sui principi di funzionamento del computer nasce però dalla peculiarità del calcolatore digitale che lo rende uno strumento unico nella storia della tecnologia, cioè l’essere un dispositivo programmabile. Tale caratteristica (il fatto di poter modificare il comportamento di un calcolatore intervenendo solo sul livello software e lasciando inalterato il suo livello hardware) ha favorito lo sviluppo di programmi sempre più ricchi di funzionalità e, allo stesso tempo, sempre più facili da usare. Ciò nonostante, non è difficile trovare persone che, pur avendo a disposizione programmi di questo genere, li utilizzano in modo scorretto o al di sotto delle loro potenzialità. L’utente dovrebbe porsi domande tipo “il software che sto usando è adatto a risolvere il mio problema?”; “quale categoria di software è più adatta a risolvere il mio problema?”; il calcolatore che sto usando è adatto a risolvere il problema?”; quale categoria di sistemi di elaborazione è la più adatta a risolvere questo genere di problemi?”. Un impiego intelligente degli strumenti messi a disposizione dalle tecnologie dell’informazione richiede e sollecita gli utenti consapevoli, capaci di coglierne potenzialità o limiti. Si vuole sottolineare l’importanza di conoscere le modalità di funzionamento del computer, così come le caratteristiche del sistema operativo in modo da ottimizzare l’uso che se ne fa; per non essere cioè semplici fruitori, privi di capacità di interagire con la macchina, “succubi” in un certo senso dello strumento stesso. D’altro canto, per ovviare a questa situazione non basta la conoscenza, anche se perfetta e del tutto esaustiva, dei singoli software o delle singole nozioni tecniche di dettaglio (quelle cioè che si trovano nei manuali di istruzioni) che vengono rese velocemente obsolete dal formidabile sviluppo tecnologico. L’IMPIEGO DELLA MACCHINA COME STRUMENTO DI ELABORAZIONE Quando l’uomo ha bisogno della macchina per elaborare informazioni? 1 Ogni giorno ogni essere umano elabora una quantità smisurata di informazioni, spesso senza sforzo apparente. In almeno due situazioni tale attività può diventare problematica, se non irrealizzabile: quando il problema che implica l’elaborazione supera un certo grado di complessità e quando viene richiesto di elaborare le informazioni con una certa rapidità. Nel corso del tempo l’uomo ha progettato strumenti che lo supportassero nell’elaborazione: - Strumenti formali, che permettono di trattare entità di informazione in via puramente elaborativa (2+2 = 4). - Strumenti materiali, che materializzando le entità di informazione ne facilitano l’elaborazione. Si tratta di strumenti, come modelli in scala di sistemi fisici o simulatori, di fatto corrispondenti a strumenti di memorizzazione meccanica. Metodi di rappresentazione dei dati Fin dai primi rudimentali sistemi di calcolo manuale, si poneva il problema di come rappresentare i dati su cui eseguire l’elaborazione. Esistono due metodi di rappresentazione: a) rappresentazione analogica b) rappresentazione digitale RAPPRESENTAZIONE ANALOGICA - Si tratta di una modalità di rappresentazione dei dati basata sull’impiego di dispositivi che realizzano una grandezza fisica che almeno in linea di principio può variare in modo continuo: ogni numero viene rappresentato mediante il corrispondente valore della grandezza considerata. Esiste un’analogia diretta tra i valori della grandezza adottata e i dati da rappresentare: per questo si definisce analogica. Si definisce analogica la rappresentazione di una grandezza ottenuta utilizzandone un’altra (di solito più comodo), di valore proporzionale, che può variare in modo continuo (cioè non a gradini) al variare della grandezza rappresentata. Un esempio: il termometro. Qui la lunghezza del tubicino colorato aumenta in modo proporzionale alla temperatura, di cui costituisce di fatto una rappresentazione analogica. Il valore numerico si ricava facilmente dalle tacche che costituiscono la scala graduata. Le tecniche analogiche nel computer solo utilizzate solo in caso di necessità; quando cioè le grandezze da osservare non si prestano ad una diretta trasformazione in valori digitali. RAPPRESENTAZIONE DIGITALE - Si tratta della modalità impiegata negli abachi, ad esempio, dove i numeri sono realizzati fisicamente come insieme di oggetti elementari, il cui numero rappresenta appunto il dato da elaborare. Stessa cosa per i dispositivi meccanici in cui i dati numerici vengono codificati secondo i movimenti delle ruote dentate rispetto ad una posizione di riferimento che rappresenta lo 0. Un metodo di rappresentazione di questo tipo trova evidentemente origine nel conteggio effettuato utilizzando le dita delle mani e per questo viene definito digitale (o anche numerico). Si definisce digitale la rappresentazione di una grandezza in modo discontinuo o a gradini; di fatto una rappresentazione di informazioni quantificabili mediante l’impiego di pochi simboli diversi fra loro. Un esempio: l’orologio digitale presenta i valori numerici corrispondenti. Durante l’intervallo di tempo di un minuto, i numeri stanno fermi per poi scattare al valore successivo mentre negli orologi a lancette, cioè analogici, il movimento è continuo. In questo caso si tratta comunque di un tipo di visualizzazione in forma digitale; il conteggio avviene invece sempre in forma analogica. 2 Altro esempio: la semplice numerazione araba o romana. Con l’uso di pochi simboli (cifre) si hanno vantaggi pratici nel rappresentare le quantità in modo chiaro e ripetibile, pur accettando un limite basilare: la rappresentazione digitale consente di indicare solo alcuni degli infiniti valori compresi in limiti prefissati. Tutti i valori in un piccolo intervallo vengono fatti coincidere in un unico valore; quanto più piccolo è l’intervallo base considerato, tanto maggiore è la cosiddetta risoluzione della rappresentazione e, corrispondentemente minori, sono gli errori di quantizzazione. In una codifica di tipo digitale, ogni configurazione assunta dal dispositivo di memorizzazione utilizzato rappresenta in genere un dato sulla base di un codice, cioè secondo una convenzione che specifica il dato rappresentato in ogni diversa configurazione. L’uomo ha costruito tradizionalmente macchine di tipo analogico dal momento che le tecnologie meccaniche spingevano in tal senso. Recentemente lo sviluppo dell’elettronica ha determinato la diffusione della tecnologia digitale. Nel campo dell’elettronica, tra le varie rappresentazioni digitali, prevale quella basata su due simboli, detta perciò digitale binaria. Per rappresentazione di un’informazione di tipo binario si intende un tipo di rappresentazione che faccia uso di due simboli. Di conseguenza si definiscono binarie le operazioni che elaborano informazioni binarie. I due simboli usualmente usati sono 0 e 1 (ereditati dall’aritmetica), o si e no oppure vero o falso (ereditato dalla logica). Se si vuole rappresentare una qualsiasi informazione in modo binario, occorre tradurla in sequenze dei due simboli scelti. Occorre evitare equivoci, cioè evitare che informazioni diverse siano tradotte nella stessa sequenza di zeri e uno. Occorre dunque fare un elenco di tutte le informazioni che si vuole considerare e definire poi una singola corrispondenza fra ogni singola informazione e ogni sequenza di simboli binari. Le rappresentazioni binarie hanno avuto successo perché è possibile costruire circuiti o apparecchi elettrici che operano in modo binario. In un circuito elettrico, lo zero e l’uno sono rappresentati tramite una grandezza elettrica; per esempio, lo zero può essere rappresentato con qualsiasi tensione elettrica compresa fra 0 e 2 volt, mentre l’uno con una tensione elettrica compresa fra 3 e 5 volt. Si definiscono di fatto due zone che vengono fatte corrispondere l’una allo 0 e l’altra all’1. La distanza fra queste due zone rappresenta il livello di rumore tollerabile dal dispositivo, cioè il valore minimo che un disturbo elettrico deve avere per trasformare uno zero in un uno o viceversa. E’ necessario trovare un supporto fisico attraverso il quale l’informazione possa essere espressa e trattata. Un supporto fisico per essere impiegato come supporto dell’informazione deve consentire di identificare delle differenze; pur trovandosi in una configurazione (ad esempio dito alzato), deve poter assumere anche una seconda configurazione (ad esempio dito abbassato). In altre parole, la condizione che crea informazione è la scelta in presenza di almeno un’alternativa; la quantità di informazione che si ottiene selezionando un elemento da un insieme che ne contiene due ha il ruolo di “unità elementare” di informazione ed è chiamata bit. La risposta “si” o “no” a una domanda porta ad 1 bit di informazione, la risposta a due domande, che corrisponde alla selezione tra 4 alternative (si-si, no-no, si-no, no-si) porta 2 bit di informazione. 3 Non c’è necessità di comprendere ciò che si rappresenta attraverso tale supporto; in questo senso, la configurazione del supporto potrebbe non significare niente e pure portare informazioni a colui che le osserva. Si tratta infatti di un’accezione puramente sintattica del concetto di informazione: i calcolatori elaborano informazioni nel senso puramente sintattico del termine. Una volta stabilito che 2+2 = 4 e questo è il risultato sintattico, saranno gli esseri umani che utilizzano i calcolatori ad associare un significato a questi simboli. ALGORITMI E PROGRAMMI Il concetto di elaborazione dell’informazione è praticamente costante nella nostra vita. Ogni problema di elaborazione è caratterizzato da un insieme di dati di partenza e da un risultato ricercato ed ogni sua soluzione è una procedura che genera un risultato sulla base dei dati indicati. Ci sono problemi di cui si conosce bene la procedura di soluzione. Ci sono una serie di problemi che ognuno risolve senza sapere esattamente la procedura (ad esempio: come si fa a muovere un braccio?) Ci sono casi in cui i dati vanno comunicati ad un soggetto che non ha elementi per mettere in pratica l’elaborazione dell’informazione. Il procedimento di soluzione di un problema deve essere realizzato in fasi distinte successive: a) analisi del problema e identificazione di una sua soluzione da parte del primo soggetto b) descrizione della soluzione da parte del primo soggetto in termini comprensibili al secondo soggetto c) Interpretazione della soluzione da parte del secondo soggetto sulla base della descrizione fornitagli dal primo d) Attuazione della soluzione da parte del secondo soggetto. Ovviamente la soluzione deve essere descritta in una forma che il soggetto esecutore sa interpretare in modo corretto e deve specificare l’esecuzione delle azioni che è in grado di attuare. Se il problema è particolarmente semplice, l’esecutore può eseguirne la soluzione direttamente sulla base di una descrizione del tipo “risolvi il problema…” Se il problema è complesso, per giungere alla descrizione della soluzione è necessario scomporre il problema in sottoproblemi e questi ancora in sottoproblemi, fino a giungere a problemi elementari (o primitivi): la soluzione di ognuno di questi problemi elementari corrisponde ad un’azione elementare che può essere direttamente compiuta dall’esecutore. La soluzione diventa effettiva per lo specifico esecutore quando: l’esecutore è in grado di interpretarne la descrizione e quindi associarla alle azioni che deve compiere; quando è in grado di compiere tale azione completandone l’esecuzione in un tempo finito. La procedura di soluzione prevede che se la soluzione del problema è effettiva l’esecutore la attua direttamente; altrimenti, il problema deve essere scomposto in sottoproblemi, in via iterativa, finchè tutti i problemi sono elementari. Dunque viene fissato l’ordine di soluzione dei problemi e viene esplicitamente specifico il modo in cui un problema utilizza i risultati dei problemi che lo precedono. L’esecutore è a sua volta caratterizzato da: un linguaggio che riesce ad interpretare; dalle azioni che è in grado di compiere; dall’insieme delle regole che ad ogni costrutto sintatticamente corretto associano le relative azioni da compiere. 4 Le soluzioni effettive per esecutori caratterizzati formalmente sono chiamati algoritmi. I calcolatori sono impiegati come esecutori di soluzioni che l’uomo ha identificato e descritto. Tale utilizzo è motivato dalla notevole velocità di esecuzione dei calcolatori e dalla loro elevata ripetibilità, cioè dalla loro capacità di eseguire molte volte la stessa operazione producendo ogni volta lo stesso risultato Il calcolatore è un esecutore formalmente caratterizzato: ha un linguaggio in grado di interpretare e con il quale devono essere descritte le soluzioni che si vuole che esso esegua e le istruzioni che è in grado di eseguire. In sintesi: L’algoritmo è la descrizione della soluzione di un problema, espressa sotto forma di un insieme di regole che, partendo dai dati iniziali, permettono di arrivare alla soluzione del problema. Le regole vengono determinate tramite la scomposizione iterativa del problema di partenza in sottoproblemi elementari; la soluzione di ognuno di questi problemi è detto step o passo dell’algoritmo. Infatti con il termine algoritmo si definisce una sequenza finita di passi (cioè costituita da un numero limitato di azioni) che devono essere effettuati per giungere in un tempo finito alla soluzione di un qualsiasi problema. La definizione si adatta molto bene alla struttura dei programmi per i calcolatori elettronici, che spesso vengono definiti come “esecutori automatici di algoritmi”. Se l’esecutore è un calcolatore, gli algoritmi vengono definiti programmi; il linguaggio formale utilizzato viene chiamato linguaggio di programmazione. Nella definizione dell’algoritmo, nell’accezione informatica del termine, ci sono due concetti di fondamentale importanza: 1) Passo = azione elementare che deve essere intrapresa allo scopo di procedere nell’esecuzione dell’algoritmo. Tale concetto richiede di stabilire l’insieme delle azioni che l’esecutore dell’algoritmo (uomo o macchina) è in grado di svolgere. In altre parole, chi definisce un algoritmo deve accordarsi con chi lo dovrà eseguire circa le istruzioni da utilizzare per descrivere l’algoritmo stesso. Per esempio: per descrivere l’algoritmo ricetta da eseguire per una frittata: l’istruzione “mettere 4 uova in padella” può essere utilizzata solo se si è sicuri che la persona che eseguirà la ricetta è in grado di capire che nella padella deve essere versato il contenuto delle uova, che devono essere quindi prima rotte in modo da eliminare i gusci. 2) Sequenza = ordine nel quale i diversi passi devono essere eseguiti per giungere al risultato. L’algoritmo non presuppone un’unica sequenza possibile di passi, ma anzi, i passi da eseguire possono variare in modo anche notevole in base alle condizioni che si incontrano quando l’algoritmo viene effettivamente eseguito. Nell’esempio della ricetta: l’esecuzione è diversa nel caso nel frigorifero non si trovino le 4 uova necessarie. In questo caso è necessario inserire l’istruzioni “andare a comprare le uova mancanti”, che deve essere eseguita solo nel caso la condizione “ci sono 4 uova nel frigo” non si verifichi. Per tener conto di questa esigenza, devono essere definite le strutture di controllo del flusso di esecuzione, cioè le direttive in base alle quali l’esecutore dell’algoritmo potrà scegliere quale strada seguire. 3) Definizione di strutture dei dati su cui l’algoritmo opera, cioè delle caratteristiche degli oggetti utilizzati per l’esecuzione dell’algoritmo stesso. Nell’esempio della ricetta, la padella necessaria è una pentola di forma particolare, di dimensioni sufficienti a contenere le 4 uova. 5 E’ necessario definire un linguaggio di comunicazione fra progettista ed esecutore; un insieme di regole di scrittura delle istruzioni, delle strutture di controllo e delle strutture di dati comprensibili per entrambi. Data la diversità dei linguaggi (programmatore parla italiano, calcolatore parla linguaggio macchina) si usano spesso traduttori che consentono l’uso di un linguaggio intermedio. E’ necessario comunque mantenere l’algoritmo sotto forma di sequenza di passi da compiere, indipendentemente dal linguaggio comprensibile al singolo esecutore, nell’ottica della possibilità di adattarlo ad esecutori diversi. Per questo si utilizzano linguaggi di rappresentazione degli algoritmi che prescindono dalle caratteristiche degli esecutori e mettono in evidenza la struttura dell’algoritmo stesso: uno di questi linguaggi è costituito dai diagrammi di flusso. La codifica dei dati Gli algoritmi sono costituti da azioni che operano su dati. Per trasformare un algoritmo in un programma (cioè in una descrizione eseguibile dal calcolatore) è necessario rappresentare entrambi, azioni e dati, in un formato adatto alla memorizzazione e manipolazione da parte di un esecutore automatico. Per formalizzare dati quali numeri e caratteri alfabetici, si utilizzano successioni di simboli, scelti da un insieme finito detto alfabeto. Ad ogni alfabeto è associato un insieme di regole di composizione che definiscono le successioni “ben formate”, cioè quelle che appunto consentono di identificare i dati. La relazione che associa ad ogni successione ben formata di simboli di un alfabeto il dato corrispondente è detto codice. Si utilizza dunque un codice, cioè una regola di rappresentazione dell’informazione. Ad esempio, un codice alfanumerico permette di rappresentare le lettere dell’alfabeto, la punteggiatura, i numeri e tutto ciò che si trova in un testo facendolo corrispondere ad un numero binario; numero che il calcolatore può memorizzare ed elaborare. Un codice di fatto mette in relazione la successione di simboli con il significato loro attribuito. E’ importantissimo adottare codici standard in modo che l’informazione codificata possa essere trasportata da un calcolatore all’altro. La codifica binaria dei dati L’alfabeto più semplice che si possa adottare per la codifica dei dati è costituito di due soli simboli, di solito indicati convenzionalmente come 0 e 1. Gli attuali calcolatori impiegano per la memorizzazione dei dati proprio dei dispositivi, detti bistabili, in grado di assumere uno stato scelto fra due differenti (per esempio in corrispondenza alla presenza o assenza di un determinato valore di tensione elettrica ai capi del dispositivo): dunque un alfabeto di questo genere, chiamato binario, si può considerare alla base dell’elaborazione automatica delle informazioni. Con il termine bistabile si identifica un circuito elettronico che può assumere due diversi stati, entrambi in modo stabile, che mantiene inalterati nel tempo finchè appositi comandi provocano la commutazione da uno stato all’altro. Questa caratteristica rende il bistabile in grado di funzionare come elemento di memoria binaria, cioè in grado di rappresentare i due valori che può assumere un bit. 6 Ogni elemento che assume un valore binario viene indicato con il termine di bit (binary digit = cifra binaria): come le cifre decimali sono gli elementi base nella rappresentazione usuale dei numeri decimali, i bit sono gli elementi dei codici utilizzati nei calcolatori. Il bit identifica una grandezza binaria, cioè un oggetto che può assumere solo due aspetti diversi di solito indicati con i valori numeri 0 e 1. Il bit è l’unità elementare di informazione, che corrisponde ad una scelta fra si e no, due risposte possono essere associate ai valori 0 e 1, le possibili configurazioni di una cifra binaria. Ad una successione di 8 bit, con cui si possono rappresentare 2 8 = 256 dati diversi, si da il nome di byte e di questo si considerano i multipli kilobyte, megabyte ecc. I PROGRAMMI Un algoritmo non è utilizzabile da un calcolatore finché non viene tradotto in linguaggio macchina. L’interesse a consentire uno sviluppo rapido e quanto più possibile facilitato di applicazioni informatiche ha portato alla definizione dei linguaggi di programmazione ad alto livello, che consentono al programmatore di descrivere i problemi ad un livello di astrazione di poco inferiore a quello degli algoritmi; quindi ancora secondo una logica più vicina al problema da risolvere che non alle caratteristiche fisiche del calcolatore impiegato. Questi linguaggi permettono di descrivere sia l’algoritmo che le componenti operative di un’applicazione informatica (ad esempio la visualizzazione dei risultati) in un formalismo che utilizza pochi termini per costruire le istruzioni, dal significato preciso ed inequivocabile, che operano sui dati nel modo desiderato. Un programma è la successione delle istruzioni che mediante un opportuno programma di traduzione possono essere trasformate in istruzioni in linguaggio macchina, quindi direttamente eseguibili dal calcolatore. Ogni linguaggio di programmazione è caratterizzato da due componenti complementari: a) la sua sintassi, cioè l’insieme delle regole che specificano come comporre istruzioni ben formate b) la sua semantica, che di ogni istruzione ben formata specifica il significato, cioè l’azione che viene compiuta quando l’istruzione sia eseguita. Con il termine PROGRAMMA si intende una rappresentazione della sequenza di operazioni necessarie per risolvere un dato problema. Un programma presuppone: a) che il problema possa essere risolto con una sequenza ben definita di operazioni (algoritmo) b) che il linguaggio, detto appunto di programmazione, sia adatto ad esprimere in modo rigoroso le operazioni c) che l’esecutore (in genere un calcolatore) sia in grado di eseguire le operazioni indicate. La funzionalità delle macchine programmabili, cioè il loro modo di operare, dipende dal programma che in un dato momento stanno eseguendo: il programma costituisce una parte fondamentale in quanto nessun calcolatore, senza un programma adatto, è in grado di svolgere anche il più banale dei compiti. I programmi hanno varie forme a seconda del linguaggio in cui sono scritti e sono classificabili in due categorie principali: a) programmi “sorgente” scritti dal programmatore per essere facilmente comprensibili e quindi sotto forma di parole, numeri e caratteri di interpunzione 7 b) programmi “oggetto” che sono in genere ottenuti dalla traduzione, effettuata dai compilatori, dei programmi sorgente e che hanno forma binaria adatta per l’esecuzione diretta da parte del calcolatore. La programmazione, cioè la produzione di programmi corretti, costituisce una delle operazioni più impegnative e in genere viene svolta attraverso una serie di strumenti (tool) che sono dei programmi di utilità presenti nel calcolatore stesso. Con il termine PROGRAMMAZIONE si intende l’insieme di attività finalizzate a realizzare i programmi necessari perché un calcolatore elettronico sia in grado di svolgere compiti e funzioni utili al mondo circostante. La programmazione nasce quindi con l’avvento dei primi calcolatori elettronici, anche se alcuni esempi si possono già trovare nei primi tentativi di macchine programmabili come l’Analitical Engine di Babbage. Programmare significa tradurre una qualsiasi funzione nella sequenza di codici macchina, che, eseguiti dall’unità centrale del calcolatore, permettono di svolgere la funzione assegnata. Fasi della traduzione: 1) Stesura delle specifiche = definizione precisa delle funzioni che il calcolatore deve svolgere, del modo in cui deve interagire con l’operatore e con l’ambiente circostante, delle decisioni che deve prendere in caso si verifichino situazioni impreviste. E’ necessario che questa fase venga svolta con accuratezza perché da questo dipende la velocità con la quale si arriva al termine del lavoro di programmazione e la qualità del risultato finale. 2) Definizione dell’algoritmo = identificazione dei passi da effettuare per svolgere le funzioni richieste. Utile strumento di lavoro in questa fase è un diagramma di flusso. 3) Codifica del programma = traduzione dell’algoritmo risolutore in una sequenza di istruzioni scritte in opportuno linguaggio di programmazione. Scelta del linguaggio macchina dovrebbe tener conto delle compatibilità delle caratteristiche del linguaggio con quelle dell’algoritmo; spesso invece la scelta è forzata dalla disponibilità di strumenti di programmazione o dalla conoscenza di uno specifico linguaggio. 4) Traduzione del linguaggio macchina del programma scritto. Questa fase è resa possibile dagli strumenti della catena di programmazione cioè dai programmi di utilità forniti insieme al calcolatore per aiutare il programmatore nelle operazioni più lunghe e noiose. 5) Collaudo del programma tradotto = prova del suo funzionamento per verificare se si comporta come previsto e se svolge tutte le funzioni richieste. L’attività di collaudo, solitamente definita come debugging, può richiedere di ripetere, in parte o per intero, alcuni dei passi precedenti, ad esempio per correggere la codifica del programma o per migliorare l’algoritmo risolutore. Le istruzioni L’elaborazione dei dati viene effettuata attraverso la successione di istruzioni che compone il corpo del programma. Nei linguaggi ad alto livello si distinguono tre classi di istruzioni: a) istruzioni di ingresso/uscita b) istruzioni aritmetico-logiche c) istruzioni di controllo 8 a) Le istruzioni di ingresso/uscita sono presenti in ogni linguaggio ad alto livello per fornire al programmatore le modalità standardizzate di acquisizione dei dati di ingresso del programma e di presentazione dei risultati. b) Le istruzioni aritmetico-logiche consentono la manipolazione dei dati e la generazione di nuovi risultati. Molti linguaggi di programmazioni includono in questa categoria, insieme alle usuali operazioni aritmetiche, anche funzioni matematiche più complesse come logaritmi, esponenziali, radici. In questa classe rientrano le operazioni di tipo logico, cioè quelle che fanno riferimento a dati di tipo booleano, come la somma e il prodotto logici, indicati più comunemente come OR e AND. c) Le istruzioni di controllo consentono di modificare il flusso di esecuzione delle istruzioni all’interno di un programma. Esistono infatti delle situazioni in cui occorre alterare l’esecuzione puramente sequenziale delle istruzioni, introducendo dei salti a istruzione presenti in un punto qualunque del programma. La strutturazione dei programmi in sottoprogrammi Programmi scritti ad alto livello raggiungono rapidamente dimensioni notevoli, nell’ordine di decine di migliaia se non di centinaia di migliaia di istruzioni. La scrittura e manutenzione di programmi di tali dimensioni sono generalmente affidate ad un gruppo di programmatori. E’ necessario organizzare i programmi in modo che la loro struttura risulti il più possibile comprensibile e modulare: in questo modo, anche coloro che non hanno contribuito direttamente alla realizzazione di una parte possono in seguito intervenire su di essa per controllarne direttamente la correttezza, eliminare gli errori riscontrati (debugging = eliminazione di bachi) ed eventualmente estenderne le funzionalità. La strutturazione di un problema in sottoproblemi e il concetto di problema terminale, descritti nel caso degli algoritmi, sono applicabili anche in questo caso. Nella strutturazione di un programma, ogni sottoproblema che sia sufficientemente ben delimitato può essere temporaneamente assunto come terminale, dunque nell’ipotesi che esista una singola istruzione del linguaggio che lo risolve. Una volta che il programma è stato completato, applicando questa strategia, si passa a considerare i sottoproblemi trattati in precedenza come terminali e per ognuno si scrive un sottoprogramma che lo risolve: in questo modo, è come se il linguaggio di programmazione che si sta utilizzando (che già dispone di un proprio insieme di istruzioni) venisse arricchito di ulteriori istruzioni, ognuna delle quali corrispondente a un sottoprogramma scritto dal programmatore. 9