Qualunque attività svolgiamo con un dispositivo elettronico, qualsiasi operazione richiediamo a un’app o a un servizio, tutto è governato da algoritmi. Un algoritmo è una “ricetta” che, passo dopo passo, stabilisce come risolvere problemi semplici e complessi. L’importanza degli algoritmi si riflette in un vasto spettro di campi applicativi. Nella medicina, gli algoritmi aiutano a diagnosticare malattie e a scoprire nuovi farmaci. Nel settore finanziario, ottimizzano il trading e la gestione dei portafogli. Nella robotica, permettono ai robot di apprendere e migliorare. Nell’e-commerce, forniscono suggerimenti personalizzati e ottimizzano la logistica.
Gli algoritmi sono il cuore pulsante dell’informatica moderna: sono alla base del funzionamento di tutte le applicazioni, dei sistemi operativi, dell’intelligenza artificiale, dei social, dei motori di ricerca e molto altro ancora. Sebbene spesso si pensi agli algoritmi come a istruzioni o procedure implementate nel software per risolvere problemi, ottimizzare processi o prendere decisioni, essi giocano un ruolo significativo anche nel mondo dell’hardware.
Cos’è un algoritmo in informatica
In informatica, un algoritmo rappresenta una serie di passaggi ben definiti e precisi eseguiti per risolvere un problema o per compiere un’operazione specifica. Gli algoritmi sono alla base della programmazione e della risoluzione dei problemi informatici.
Un algoritmo è formato da una sequenza di istruzioni da eseguire nell’ordine prestabilito al fine di raggiungere il risultato desiderato. Gli algoritmi possono essere rappresentati in diverse forme, ricorrendo a diagrammi, pseudocodice o codice di programmazione vero e proprio.
Le caratteristiche essenziali di un algoritmo
- Chiarezza e precisione: Gli algoritmi devono essere definiti in modo chiaro, preciso e senza ambiguità, in modo che chiunque li utilizzi possa ottenere lo stesso risultato.
- Finito e deterministico: Gli algoritmi devono terminare dopo un numero finito di passaggi e fornire un risultato definito per ogni input. Devono essere prevedibili e non lasciare spazio a interpretazioni casuali.
- Risolve problemi specifici: Gli algoritmi sono sviluppati al fine di risolvere problemi specifici, che possono riguardare calcoli matematici, organizzazione e manipolazione di dati, gestione di algoritmi di ricerca od ordinamento e così via.
- Efficienza: Un buon algoritmo cerca di risolvere un problema nel minor tempo possibile e con il minor utilizzo di risorse disponibili, come memoria o processore.
Una volta definiti, gli algoritmi possono essere implementati in diversi linguaggi di programmazione per risolvere problemi pratici, come sviluppare software, gestire database, creare modelli di intelligenza artificiale. Tanto per fare qualche esempio.
Da cosa deriva il nome algoritmo
Il termine “algoritmo” deriva dal nome del matematico persiano Muhammad ibn Musa al-Khwarizmi, vissuto nell’ottavo e nono secolo. Il suo nome è stato latinizzato come “Algoritmi” e successivamente trasformato nel termine “algoritmo“.
Al-Khwarizmi ha svolto un ruolo significativo nello sviluppo dell’algebra e dei metodi computazionali. I suoi scritti contenevano metodi per risolvere equazioni e problemi algebrici, offrendo un contributo notevole allo sviluppo della matematica e della risoluzione dei problemi.
Il concetto di algoritmo è stato formalizzato e ampliato nel tempo, soprattutto con il contributo di altri matematici ed esperti di logica nel corso della storia. Uno dei punti di svolta nella definizione formale degli algoritmi è stato il lavoro di David Hilbert e di altri matematici nel XX secolo. L’introduzione della “macchina di Turing” da parte dell’informatico britannico Alan Turing, negli anni ’30, ha permesso di congegnare un modello astratto di calcolo e ha dimostrato la potenza e i limiti dei calcolatori matematici.
Esempi di algoritmi utilizzando diversi linguaggi di programmazione
Come abbiamo evidenziato in precedenza, un algoritmo si traduce in una sequenza di passaggi utili a risolvere qualunque genere di problema. Spesso un algoritmo può acquisire dei dati in ingresso (input) per poi produrre, a valle di una serie di elaborazioni, dei dati in uscita (output).
Algoritmo Bubble Sort
Uno degli esempi classici di algoritmo è il Bubble Sort. Si tratta di un algoritmo di ordinamento che scorre ripetutamente attraverso la lista fornita in input, confrontando gli elementi adiacenti e scambiandoli se sono in ordine sbagliato. Continua a svolgere l’operazione fintanto che l’intera lista non è ordinata. L’algoritmo Bubble Sort può essere ovviamente implementato con qualunque linguaggio di programmazione. In Python è possibile renderlo così:
def bubble_sort(arr):
n = len(arr)
for i in range(n):
for j in range(0, n-i-1):
if arr[j] > arr[j+1]:
arr[j], arr[j+1] = arr[j+1], arr[j]
# Utilizzo
array = [64, 34, 25, 12, 22, 11, 90]
bubble_sort(array)
print("Array ordinato:", array)
Nell’esempio, la funzione bubble_sort()
è proprio l’algoritmo Bubble Sort. Il codice riportato al di sotto del commento # Utilizzo
non fa altro che passare a tale funzione una lista di numeri , sotto forma di array, da ordinare.
Algoritmo di ricerca binaria
La ricerca binaria è un altro algoritmo di ricerca che si occupa di individuare il valore d’interesse all’interno di un elenco ordinato dividendo ripetutamente la ricerca a metà. Di seguito un esempio di codice C++:
#include <iostream> using namespace std; int binary_search(int arr[], int left, int right, int target) { while (left <= right) { int mid = left + (right - left) / 2; if (arr[mid] == target) return mid; if (arr[mid] < target) left = mid + 1; else right = mid - 1; } return -1; } // Utilizzo int main() { int arr[] = {11, 12, 22, 25, 34, 64, 90}; int target = 34; int n = sizeof(arr) / sizeof(arr[0]); int result = binary_search(arr, 0, n - 1, target); (result == -1) ? cout << "Elemento non trovato." : cout << "Elemento trovato alla posizione: " << result; return 0; }
Algoritmo per il calcolo del fattoriale
Quello per il calcolo del fattoriale è un algoritmo che restituisce il prodotto di tutti i numeri interi positivi fino a un certo numero. Nell’esempio di seguito effettuiamo questo tipo di elaborazione ricorrendo a codice JavaScript:
function factorial(n) {
if (n === 0 || n === 1)
return 1;
else
return n * factorial(n - 1);
}
// Utilizzo
const number = 5;
const result = factorial(number);
console.log(`Il fattoriale di ${number} è: ${result}`);
L’esempio calcola il fattoriale di 5: ovviamente il valore della costante number
è liberamente personalizzabile. Il fattoriale di 5 è calcolato come 5! = 5 x 4 x 3 x 2 x 1 = 120
. Il risultato è stampato nella console del browser (console.log
).
Aspetti importanti da considerare quando si sviluppano algoritmi
Gli algoritmi sono alla base di molte innovazioni tecnologiche. Dalle reti neurali artificiali per l’apprendimento automatico, al funzionamento dei motori di ricerca, alla crittografia, gli algoritmi guidano il progresso tecnologico.
L’analisi della complessità degli algoritmi è fondamentale. Lo sviluppatore è chiamato a verificare quanto tempo o risorse un algoritmo richiede al crescere delle dimensioni del problema. In questo modo si possono stabilire quali algoritmi sono più efficienti per risolvere un determinato problema.
Alcune varianti dei vari algoritmi possono risolvere lo stesso problema in modo più efficiente e impegnando un volume inferiore di risorse. Per questo l’ottimizzazione degli algoritmi è un’attività imprescindibile che guarda al miglioramento dell’efficienza e delle prestazioni. Gli algoritmi, insomma, non sono statici ma sono soggetti a revisioni e sviluppi costanti.
Le abilità in fatto di astrazione e la capacità di analizzare e scomporre logicamente un problema sono essenziali per la progettazione e lo sviluppo di algoritmi efficaci.
Con la crescente domanda di applicazioni basate sull’intelligenza artificiale e la richiesta di sistemi decisionali, sorge la necessità di considerare anche l’aspetto etico degli algoritmi, soppesando problemi come la trasparenza, l’imparzialità e l’equità.
Algoritmi e hardware
Come abbiamo accennato in apertura, gli algoritmi sono utilizzati non solo a livello software, ma anche nell’hardware. Nella progettazione dei circuiti integrati (come i processori, le schede grafiche, i chip specializzati,…), appositi algoritmi permettono di ottimizzare l’architettura del circuito, minimizzare la latenza, ridurre il consumo di energia e massimizzare le prestazioni.
Nei compilatori, appositi algoritmi convertono il codice sorgente scritto in un linguaggio ad alto livello in istruzioni che lo specifico processore può eseguire. In un altro articolo ci siamo concentrati sulle differenze tra compilazione e interpretazione. Gli algoritmi di ottimizzazione del codice svolgono un ruolo cruciale nel riscrivere le istruzioni fornite del programmatore in modo più efficiente. In questo modo è possibile ridurre le operazioni eseguite e migliorare la gestione delle risorse.
Citiamo anche gli algoritmi di controllo, utilizzati ad esempio per regolare la velocità delle ventole in un computer in base alla temperatura o per ottimizzare la distribuzione di energia in un sistema embedded.
Nelle architetture hardware specializzate, come GPU, unità tensoriali (TPU) e FPGA, appositi algoritmi si occupano di gestire attività quali l’elaborazione parallela, il machine learning, la crittografia e così via.
L’immagine in apertura è di Google DeepMind (Unsplash).