Calcolatore (2) - Programmazione
(clicca per una versione in cui si considerano i primi linguaggi di programmazione)
Alle calcolatrici non programmabili
possiamo far eseguire solo singole operazioni di:
addizione, moltiplicazione,
e calcolo di altre funzioni per cui hanno programmi incorporati
immagazzinamento o estrazione di dati dalle memorie-utente.
A un calcolatore (o computer o macchina
calcolatrice programmabile) [ calcolatore 1] possiamo far gestire
l'esecuzione di tutto un algoritmo: esso infatti accetta come
informazioni provenienti dall'esterno:
non
solo dati e specifici comandi,
ma
anche programmi che gli indicano l'ordine con cui dovrà
utilizzare i programmi incorporati per elaborare i dati che gli
verranno forniti dall'esterno.
Che cosa deve essere in grado di fare un computer per eseguire un programma fornito dall'utente, cioè per tradurlo in una sequenza di operazioni-macchina?
Consideriamo ad esempio il calcolo della ripartizione percentuale di una serie di dati. Usando una CT possiamo procedere in questo modo:
(1) | batto 100 | (#) |
(2) | batto | |
(3) | batto totale | |
(4) | batto | faccio calcolare il fattore di proporzionalità per cui moltiplicare i dati |
(5) | batto | lo faccio mettere nella memoria |
(6) | batto dato | |
(7) | batto | |
(8) | batto | |
(9) | batto | faccio calcolare la percentuale di dato rispetto a totale |
(10) | ritorno a (6) | vado a introdurre un nuovo dato |
Come si vede, è l'utente che deve
gestire l'esecuzione dell'algoritmo (#), cioè comandare
alla CT man mano quale operazione compiere.
I calcolatori sono invece in grado di
"leggere" e tradurre automaticamente in una sequenza di
operazioni-macchina (calcoli, memorizzazioni,
)
un programma che illustri l'intero procedimento, cioè
una descrizione dell'algoritmo (#) fatta in un opportuno linguaggio
"comprensibile" dal calcolatore.
Molti computer tascabili (o pocket
computer) e tutti i calcolatori di maggiori dimensioni sono in
grado di eseguire il seguente programma (##) scritto
in linguaggio Basic:
10 | INPUT T | l'utente deve battere totale |
20 | K = 100/T | (##) |
30 | INPUT D | l'utente deve battere dato |
40 | PRINT D*K | |
50 | GOTO 30 |
È facile comprendere il significato di questo programma, che ha la forma di una sequenza di istruzioni numerate. PRINT in inglese significa "stampa"; GOTO deriva dall'inglese "go to", che significa "vai a". La parola INPUT, che abbiamo già usato |
? 1500 ? 200 13.33333 ? 300 20 ? 100 6.666667 ? |
Per poter eseguire un programma come (##)
un pocket computer deve essere in grado di memorizzare il
testo del programma, cioè, nel caso di (##), la seguente
sequenza di caratteri, dove con"ø" e con
10øINPUTøT20øK=100/T30øINPUTøD40øPRINTøD*K50øGOTOø30
Come le usuali CT memorizzano i numeri
sotto forma di sequenze di bit, così un pocket computer
memorizza sotto forma di una sequenza di bit anche il testo del
programma, utilizzando uno specifico codice.
Deve, inoltre, essere in grado (quando
l'utente gli comanda, con un opportuno tasto, di eseguire
il programma) di leggere (la sequenza di bit con cui
ha codificato) il programma e decidere, man mano, quale operazione
eseguire: una memorizzazione, un richiamo dalla memoria, un
calcolo o una visualizzazione (operazioni che nelle CT non
programmabili vengono comandate direttamente da tastiera), o un
trasferimento dell'esecuzione a un altro punto del programma.
Per fare tutto ciò, il pocket computer
deve avere:
un
"programma incorporato" per codificare il "programma
battuto dall'utente",
un
dispositivo di memorizzazione in cui registrare il programma
codificato,
almeno
26 memorie-utente (memoria A, memoria B,
, memoria Z)
da associare alle diverse lettere dell'alfabeto e
un
ulteriore "programma incorporato" per tradurre
il programma codificato nell'azionamento dei vari dispositivi di
calcolo, memorizzazione,
.
Esistono versioni più sofisticate del
linguaggio Basic e molti altri linguaggi di programmazione in cui, tra l'altro, si possono usare come variabili
non solo lettere ma nomi composti da più caratteri e in cui non è
necessario scrivere in testa a ogni riga di programma un numero
che indichi l'ordine in cui va eseguita. Poiché richiedono dei
programmi di traduzione più complicati, oltre a una maggiore capacità di memorizzazione
(possono impiegare un numero molto più alto di variabili), esse vengono impiegate solo su
personal computer o su calcolatori di dimensioni maggiori.
Noi useremo due linguaggi particolari, d'uso gratuito e diffusi su tutti i tipi di computer.
Se clicchi qui si apre una finestra
in cui è incorporato un programma scritto in
Javascript. Gli input e gli output sono inseriti in diverse finestrelle invece che elencati
uno sotto l'altro.
Se invece clicchi qui trovi come scaricare
R, una delle applicazioni matematiche più usate, e che avremo modo di
impiegare parecchie volte. Vediamo, ora, uno dei modi in cui eseguire con essa il calcolo descritto sopra.
Basta che copi le righe seguenti e, aperto R, ve le incolli:
tot <- 1500; perc <- 100/tot
d <- 150; d*perc
Ottieni:
[1] 10
Poi con il tasto "freccia su" richiami l'ultima riga, con i tasti "freccia a destra" e
"freccia a sinistra" ti posizioni a destra di "150", con il tasto "backspace" cancelli "150"
e batti "250", e poi batti "a_capo"; ottieni;
d <- 250; d*perc
[1] 16.66667 .
Un computer (personal computer o di dimensioni maggiori), a differenza del pocket computer di cui abbiamo parlato prima, non ha un unico programma traduttore "incorporato", ma è in grado di tradurre in operazioni-macchina un programma scritto in un qualunque linguaggio di programmazione, a patto che gli venga fornito in "input" anche un opportuno programma traduttore.
La CPU di un computer può eseguire direttamente solo un programma che le arrivi sotto forma di una sequenza di bit che, a gruppi, rappresentino direttamente le operazioni-macchina da effettuare. Il linguaggio (che ha come alfabeto i simboli 0 e 1) in cui vengono scritti questi programmi viene detto linguaggio macchina.
I linguaggi di programmazione come i Basic o come il più sofisticato R
non descrivono direttamente singole operazioni-macchina, ma, come abbiamo visto,
impartiscono comandi più comlessi (a cui corrispondono più comandi del linguaggio-macchina), usano come caratteri quasi tutti i simboli della tastiera e indicano i comandi con nomi che ne richiamano il significato; per questo vengono detti linguaggi evoluti (o di alto livello). Per usare un linguaggio evoluto in genere non si dota il computer solo di un programma traduttore ma di un programma in linguaggio macchina più articolato, che funge da vero e proprio ambiente di programmazione, cioè un programma che contiene come sottoprogrammi:
un programma redattore (editor) per registrare sotto forma di byte i caratteri battuti dall'utente, ad esempio registrare col nome "percent.bas" il testo del programma (###); in genere è presente anche un help, che richiama uso e significato dei comandi, propone esempi,
.
Un editor è una applicazione per leggere/elaborare testi (come NotePad/BloccoNote in Windows e SimpleText in Mac) che registra i documenti codificando i vari caratteri (lettere, cifre, virgole, spazi bianchi, e altri simboli) attraverso byte, ossia sequenze di 8 bit (i caratteri codificabili in questo modo sono 256; infatti le diverse sequenze di 8 cifre che riesco a costruire con 0 e 1 sono
2·2·2·2·2·2·2·2 = 28 = 256).
Il codice impiegato è chiamato ASCII (pronuncia: aski).
Ad esempio "P" è codificato con 01010000 (che interpretato come numero in base 2 corrisponde in base dieci a 16+64 = 80), l'"a capo" con 00001101 (che in base dieci diventa 1+4+8 = 13); si dice che 01010000, o più frequentemente che 80, è il codice ASCII di "P".
[codice simile all'ASCII, usatissimo, è l'UTF-8; in R la codifica/decodifica è
visionabile coi comandi "utf8ToInt" e "intToUtf8"; ad esempio utf8ToInt("P"); intToUtf8(80); intToUtf8(13)
danno come uscite 80, "P" e "\r".
Clicca QUI per una tabella che descrive il codice ascii]
un
programma traduttore per tradurre la sequenza di bit
costruita dall'editor, cioè il programma in linguaggio evoluto,
in una sequenza di bit che sia la versione in linguaggio macchina del
programma. Nel caso dei Basic abbiamo una finestra di lista per la descrizione del programma e una
finestra di output per le uscite; nel caso di R tutto
avviene in un'unica finestra.
In un ambiente di programmazione la
traduzione in linguaggio macchina può essere avviata operando con il mouse su un menu a cascata
o premendo una opportuna combinazione di
tasti. Nel caso di R per la traduzione ed esecuzione basta un "a capo".
In altri casi si tratta di un comando (Compile o Make EXE o
) che ordina la traduzione
del programma in linguaggio macchina e la sua registrazione sul disco fisso o su un altro supporto di memorizzazione.
La versione in linguaggio macchina può essere avviata successivamente, anche al di fuori dell'ambiente di
programmazione. Questo tipo di traduzione, che comporta la creazione e registrazione di un programma autonomo
(un file eseguibile), viene detta compilazione.
I programmi "originali", in linguaggio evoluto, vengono detti programmi
sorgenti.
Nello
stendere un programma in un linguaggio evoluto dobbiamo tener presenti
delle regole di scrittura che garantiscano che il testo battuto sia
effettivamente traducibile in linguaggio macchina. L'insieme di
queste regole di scrittura viene detto sintassi.
Anche
nella lingua naturale esistono delle regole sintattiche. Ad esempio
uno dei modi in cui si può comporre una frase in italiano
è: articolo+nome+verbo dove articolo,
nome e verbo devono essere raccordati in numero
(sing./plu.) e, eventualmente, in genere (m/f), e rispettare
altre eventuali condizioni (es.: davanti ai nomi maschili singolari se
iniziano con z, x, gn, pn, ps, s
seguita da consonante o i seguita da vocale si può mettere
uno non un; negli altri casi si può mettere un,
non uno). Ma
si tratta di regole che spesso presentano eccezioni e su cui spesso
esistono opinioni contrastanti (ad es.qualcuno sostiene che davanti a
pn - pneumatico, pneumotorace,
- occorre, o si può,
usare un). In realtà non si tratta di "regole" ma di
Poi,
anche se ci esprimiamo in modo un po' sgrammaticato, in genere ci
capiamo allo stesso (di fronte al cartello «attendi - lo cane
morzica» non abbiamo difficoltà a interpretarlo come
«Attenti: il cane morsica»).
Nel
caso dei linguaggi di programmazione le regole sintattiche sono invece
definite senza ambiguità ed eccezioni (per questo si parla di
linguaggi formali) e devono essere rispettate
rigorosamente: se il linguaggio di programmazione contiene l'istruzione print che
comanda la stampa di ciò che viene scritto dopo di essa e si
è scritto prlnt (una "l" al posto della "i") il programma traduttore
non può meccanicamente individuare l'operazione che l'utente
voleva indicare.
L'help indica le regole sintattiche da rispettare per costruire i programmi.
Ecco nel caso di R una parte dell'help relativa alle assegnazioni, come
l'istruzione perc <- 100/tot (in Basic le assegnazioni
avevano la forma
Assignment Operators Description Assign a value to a name. Usage x <- value value -> x x = value Arguments x a variable name value a value to be assigned to x.
Mentre "usage" e "arguments" illustrano la sintassi, "description" spiega
in breve la semantica delle assegnazioni, cioè
come esse vengono tradotte in linguaggio macchina (ossia il loro "significato; nel caso del linguaggio comune la semantica
si riferisce al significato di parole e frasi, qui a quello di istruzioni e programmi).
Una spiegazione più dettagliata nel caso delle assegnazioni di valori numerici
è presente alla voce
struttura di un termine: vengono associati dei registri di memorizzazione alle
variabili che compaiono nella assegnazione e poi vengono man mano calcolati i valori intermedi utilizzando eventualmente
altri registri di lavoro, fino al calcolo del risultato finale e la sua memorizzazione nel registro associato alla
variabile a cui punta la freccia.
[nella descrizione precedente "x" e "value" fungono da variabili sintattiche, cioè sono nomi che indicano
generiche espressioni del linguaggio]
Anche tra gli "errori" esiste una distinzione tra quelli sintattici e quelli semantici. Facciamo due semplici esempi, riferendoci al linguaggio R, ma è facile trasferirli a qualsiasi altro linguaggio.
f = function(x) x/(sqrt(4)-2) |
if(0 > 1) "a" else "b" |
La prima riga a sinistra è scritta rispettando le regole sintattiche del linguaggio; infatti appena premo "invio"
non compare alcun messaggio che segnali la presenza di errori "sintattici": il programma riesce a leggere e
ad interpretare l'istruzione. Ma nella seconda riga, in cui comando di calcolare il valore di f per un
certo dato (0 o un numero qualunque), viene segnalato un errori "semantico" (un "errore in corso di esecuzione"):
il programma nell'eseguire le azioni comandate si trova di fronte al calcolo di un termine indefinito.
Nel caso a destra non vi sono né errori sintattici né errori semantici: il
computer dà come uscita "b" senza visualizzare alcun messaggio. La
condizione 0>1 è scritta
correttamente (non presenta errori sintattici) e il computer riesce a
darle un significato, cioè a determinare che è
una condizione "falsa" (non presenta errori semantici)
Vi sono anche le assegnazioni stringa:
una stringa è una sequenza di caratteri, un termine stringa
è una costante stringa (ossia una sequenza di caratteri
racchiusa tra virgolette), una variabile a cui sia stato
assegnato un termine stringa
oppure una espressione costruita a partire da costanti e
variabili stringa mediante concatenazioni (l'operazione di concatenazione in Basic è indicata
con "+", in R col comando "paste").
Esempio: in R
In R (come abbiamo visto negli esempi riportati) più istruzioni possono stare sulla stessa riga se separate da ";". Un'istruzione può essere spezzata su più righe; più istruzioni possono essere accorpate se racchiuse da una coppia di parentesi graffe. Le istruzioni di "input" sono realizzabili mediante il comando "scan".
Esercizi: testo e soluzione, testo e soluzione
Per altri esempi (in R e in JS) ed altro software rinviamo al link programmi apribili accessibile da .
I primi calcolatori programmabili (di enormi dimensioni) risalgono agli anni immediatamente successivi alla II guerra mondiale. Comunque l'idea di computer fu messa a fuoco da Alan Turing, nel 1936, 15 anni prima delle realizzazione pratica dei primi modelli di computer: egli formalizzò il concetto generale di algoritmo e mise a punto il primo linguaggio di programmazione. Vedi qui per approfondimenti.
I primi personal computer [ calcolatore 1]
fanno la comparsa dopo il 1975, ma un computer di piccole dimensioni fu messo a punto dalla Olivetti già nel 1964 (il P101).
A fianco è raffigurato un modello di HP85 (1979), il primo personal computer di piccole dimensioni
(con incorporata una stampante, un lettore/registratore di dati e programmi su cassette magnetiche)
ad avere una grossa diffusione in tutto il mondo. Qualche anno dopo (1984) si sviluppano (prima in ambito Mac e, da un certo punto in poi, soprattutto, in ambito Windows) personal computer che utilizzano il mouse. Successivamente (in Italia a partire dal 1986) si diffonde l'uso di Internet e, poi, la possibilità di impiegare software via rete, in modo interattivo. | |
Dopo si sviluppano gli schermi sensibili al tatto,
i cellulari diventano, per vari aspetti, dei piccoli personal computer,
Si sono diffusi negli ultimi anni anche i tablet, delle specie di piccoli personal computer senza "tastiera fisica" (hanno lo schermo sensibile al tatto). Sono comodi per leggere testi e scriverne (almeno per chi non ha problemi di dislessia), fare foto o filmati, ascolare brani musicali, , ma non per fare cose più significative. Per dirla con Dan Gookin, "se nella vita digitale vi sentite solo di passaggio, allora potete cavarvela con uno smartphone o un tablet e non aver mai bisogno di un PC; se però avete bisogno di creare qualcosa, allora vi serve un computer" (da PCs For Dummies). |