Guida per sviluppatori alla conversione di basi: binario, esadecimale, ottale e decimale
Un pomeriggio stai fissando 0x7FFF5FBFF8C0 in un debugger, poi passi a un file CSS per ritoccare #FF5733, poi esegui chmod 755 in un terminale. Tre rappresentazioni numeriche diverse, stessa aritmetica sottostante. Se ti sei mai fermato a convertire mentalmente tra esadecimale e binario, o ti sei chiesto perché i permessi Unix usano proprio l’ottale, questa guida farà scattare quei collegamenti.
Percorreremo i quattro sistemi numerici che compaiono nella programmazione quotidiana, i tre metodi di conversione che vale la pena memorizzare e codice reale in JavaScript, Python, Go e C. Se vuoi saltare la teoria e convertire un numero, apri il nostro Convertitore di basi: gestisce qualsiasi base da 2 a 36 con precisione arbitraria.
I quattro sistemi numerici che ogni sviluppatore usa
Ogni base esiste nella programmazione per una ragione pratica, non per accidente storico.
Binario (base 2) — Il linguaggio della macchina
Due cifre: 0 e 1. Un transistor è acceso o spento: quel vincolo fisico ci dà il binario. Lo incontrerai direttamente quando lavori con bitmask, feature flag, operazioni bitwise e calcoli di subnet IP.
Il binario diventa rapidamente ingombrante. Il numero decimale 255 è 11111111 in binario: otto cifre per un valore che sta in tre cifre decimali. È esattamente per questo che i programmatori scrivono raramente binario grezzo, tranne quando contano le posizioni dei singoli bit.
Ottale (base 8) — La scorciatoia Unix
Otto cifre: da 0 a 7. Ogni cifra ottale mappa esattamente a tre bit binari, ed è per questo che i permessi dei file Unix usano l’ottale: chmod 755 impacchetta tre gruppi di tre bit di permesso in tre cifre leggibili.
L’ottale aveva un ruolo più ampio nell’era dei PDP-11, quando le parole di macchina si dividevano pulitamente in gruppi da 3 bit. Oggi è principalmente una cosa dei permessi Unix, più l’occasionale letterale C con prefisso 0 (che ha causato non pochi bug off-by-one quando qualcuno scrive 0177 aspettandosi il decimale 177).
Decimale (base 10) — Il default umano
Dieci cifre: da 0 a 9. Questo è il sistema su cui il tuo cervello fa il default: numeri di porta, indici di array, codici di stato HTTP, dimensioni in pixel. I computer non pensano in decimale, ma gli umani sì, quindi ogni numero rivolto all’utente esce in base 10.
Esadecimale (base 16) — Il coltellino svizzero dello sviluppatore
Sedici simboli: 0-9 e A-F. Ogni cifra esadecimale rappresenta esattamente quattro bit binari (un nibble), il che rende l’esadecimale la rappresentazione compatta ideale dei dati binari. Due cifre esadecimali = un byte. Sempre.
Vedrai esadecimale negli indirizzi di memoria (0x7FFF5FBFF8C0), nei colori CSS (#FF5733), negli indirizzi MAC (00:1A:2B:3C:4D:5E), nella formattazione UUID e nei digest hash. È la lingua franca della programmazione a livello di byte.
Prova a convertire tra tutti e quattro i sistemi nel nostro Convertitore di basi: digita un valore in qualsiasi base e guarda gli altri aggiornarsi all’istante.
Come funziona la conversione di base: tre metodi fondamentali
Non ti serve uno strumento per convertire tra basi, anche se uno certamente velocizza le cose. Tre metodi coprono ogni caso.
Metodo 1 — Espansione posizionale (qualsiasi base → decimale)
Ogni sistema numerico posizionale funziona allo stesso modo: ogni cifra è moltiplicata per la base elevata alla potenza della sua posizione, contando da destra partendo da zero.
Binario 1011:
1×2³ + 0×2² + 1×2¹ + 1×2⁰
= 8 + 0 + 2 + 1
= 11
Esadecimale FF:
15×16¹ + 15×16⁰
= 240 + 15
= 255
Nel codice, la maggior parte dei linguaggi gestisce questo con una funzione di parsing:
parseInt('1011', 2) // 11
parseInt('FF', 16) // 255
parseInt('755', 8) // 493
Metodo 2 — Divisione ripetuta (decimale → qualsiasi base)
Per andare nell’altra direzione, dividi il numero decimale per la base obiettivo ripetutamente e raccogli i resti. Leggi i resti dal basso verso l’alto.
Decimale 255 → esadecimale:
255 ÷ 16 = 15 resto 15 (F)
15 ÷ 16 = 0 resto 15 (F)
→ Leggi verso l'alto: FF
Decimale 42 → binario:
42 ÷ 2 = 21 resto 0
21 ÷ 2 = 10 resto 1
10 ÷ 2 = 5 resto 0
5 ÷ 2 = 2 resto 1
2 ÷ 2 = 1 resto 0
1 ÷ 2 = 0 resto 1
→ Leggi verso l'alto: 101010
bin(42) # '0b101010'
hex(255) # '0xff'
oct(493) # '0o755'
Metodo 3 — Raggruppamento di bit (binario ↔ esadecimale/ottale diretto)
Questo è il metodo che gli sviluppatori esperti usano di più. Poiché 16 = 2⁴ e 8 = 2³, puoi convertire tra binario ed esadecimale (o ottale) raggruppando direttamente i bit, senza aritmetica.
Binario → esadecimale: raggruppa in nibble (4 bit) da destra. Riempi il gruppo più a sinistra con zeri se necessario.
Binario: 1010 1111
Esadec.: A F
→ AF
Binario → ottale: raggruppa in triplette (3 bit) da destra.
Binario: 111 101 101
Ottale: 7 5 5
→ 755
La tabella di lookup dei nibble vale la pena memorizzarla:
| Binario | Esad. | Binario | Esad. |
|---|---|---|---|
0000 | 0 | 1000 | 8 |
0001 | 1 | 1001 | 9 |
0010 | 2 | 1010 | A |
0011 | 3 | 1011 | B |
0100 | 4 | 1100 | C |
0101 | 5 | 1101 | D |
0110 | 6 | 1110 | E |
0111 | 7 | 1111 | F |
Una volta interiorizzata questa tabella, la conversione binario-esadecimale diventa un’operazione di sguardo-e-lettura.
Conversione di basi in ogni linguaggio
Ecco come gestire la conversione di basi numeriche nei quattro linguaggi dove compare di più.
JavaScript / TypeScript
// Parsing: stringa in qualsiasi base → numero
parseInt('FF', 16) // 255
parseInt('101010', 2) // 42
parseInt('755', 8) // 493
// Formattazione: numero → stringa in qualsiasi base
(255).toString(16) // 'ff'
(42).toString(2) // '101010'
(493).toString(8) // '755'
// Letterali
const bin = 0b11111111; // 255
const oct = 0o377; // 255
const hex = 0xff; // 255
// BigInt per valori oltre 2⁵³
const big = BigInt('0xFFFFFFFFFFFFFFFF');
big.toString(2) // 64 uno
big.toString(10) // '18446744073709551615'
Python
# Decimale → altre basi (restituisce stringhe con prefisso)
bin(255) # '0b11111111'
oct(493) # '0o755'
hex(255) # '0xff'
# Altre basi → decimale
int('11111111', 2) # 255
int('FF', 16) # 255
int('755', 8) # 493
# Output formattato con padding
f'{255:08b}' # '11111111' (binario a 8 cifre, riempito con zeri)
f'{255:02x}' # 'ff' (esadecimale a 2 cifre, minuscolo)
f'{255:02X}' # 'FF' (esadecimale a 2 cifre, maiuscolo)
# Gli interi Python hanno precisione arbitraria di default
big = int('F' * 64, 16) # numero a 256 bit, nessun overflow
Go
package main
import (
"fmt"
"strconv"
)
func main() {
// Formattazione: int → stringa in qualsiasi base
fmt.Println(strconv.FormatInt(255, 16)) // "ff"
fmt.Println(strconv.FormatInt(255, 2)) // "11111111"
fmt.Println(strconv.FormatInt(493, 8)) // "755"
// Parsing: stringa in qualsiasi base → int
n, _ := strconv.ParseInt("FF", 16, 64) // 255
fmt.Println(n)
// Verbi Printf
fmt.Printf("%b %o %x %d\n", 255, 255, 255, 255)
// 11111111 377 ff 255
}
C
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
int main() {
// Output in decimale, ottale, esadecimale
printf("%d %o %x\n", 255, 255, 255);
// 255 377 ff
// Parse da qualsiasi base
long val = strtol("FF", NULL, 16); // 255
long bin = strtol("101010", NULL, 2); // 42
// Nessun printf binario integrato — estrazione manuale:
uint8_t byte = 0xAF;
for (int i = 7; i >= 0; i--)
putchar(((byte >> i) & 1) ? '1' : '0');
// 10101111
return 0;
}
Scenari reali di conversione di base
Cinque situazioni in cui la conversione di base smette di essere accademica e inizia a essere parte del lavoro.
1. Debug di indirizzi di memoria
Il tuo debugger mostra un puntatore a 0x7FFF5FBFF8C0. Convertire gli ultimi due byte in binario — 1000 1100 0000 — rivela che l’indirizzo è allineato a un confine di 64 byte (sei zeri finali). L’allineamento conta per le prestazioni della cache, le operazioni SIMD e l’I/O memory-mapped. La rappresentazione esadecimale rende questi pattern visibili a colpo d’occhio.
L’aritmetica dei puntatori è anche più facile da ragionare in esadecimale. L’offset 0x100 da un indirizzo base è esattamente 256 byte — una pagina in molti sistemi embedded. In decimale è meno ovvio.
2. Colori esadecimali CSS ↔ RGB
Il colore #FF5733 è composto da tre byte impacchettati come coppie esadecimali:
| Coppia | Esadec. | Decimale | Canale |
|---|---|---|---|
FF | FF | 255 | Rosso (max) |
57 | 57 | 87 | Verde |
33 | 33 | 51 | Blu |
La notazione abbreviata come #F00 si espande a #FF0000: rosso puro. La variante a 8 cifre #FF573380 aggiunge un canale alpha dove 80 (decimale 128) è circa il 50% di opacità.
Conoscere la mappatura esadecimale-decimale significa meno viaggi a un selettore di colore quando vuoi alzare o abbassare un canale di una quantità specifica.
3. Permessi dei file Unix (ottale)
chmod 755 si scompone come:
7 → 111 → rwx (proprietario: lettura + scrittura + esecuzione)
5 → 101 → r-x (gruppo: lettura + esecuzione)
5 → 101 → r-x (altri: lettura + esecuzione)
Ogni cifra ottale codifica esattamente un gruppo di permessi perché tre bit di permesso (lettura=4, scrittura=2, esecuzione=1) mappano a una cifra ottale (0-7). Pattern comuni:
| Ottale | Binario | Permessi | Uso tipico |
|---|---|---|---|
755 | 111 101 101 | rwxr-xr-x | Eseguibili, directory |
644 | 110 100 100 | rw-r--r-- | File regolari |
700 | 111 000 000 | rwx------ | Script privati |
600 | 110 000 000 | rw------- | Chiavi SSH, segreti |
4. Calcoli di subnet di rete
Una maschera di subnet /24 significa 24 uno iniziali in binario:
11111111.11111111.11111111.00000000
→ 255.255.255.0
Per trovare l’indirizzo di rete, fai l’AND tra IP e maschera in binario:
192.168.1.37 → 11000000.10101000.00000001.00100101
255.255.255.0 → 11111111.11111111.11111111.00000000
Risultato AND → 11000000.10101000.00000001.00000000
→ 192.168.1.0 (indirizzo di rete)
Gli ingegneri di rete convertono di routine tra decimale (notazione IP), binario (matematica delle subnet) e a volte esadecimale (cattura di pacchetti). Il nostro Convertitore di basi gestisce ogni ottetto individualmente se preferisci una verifica visiva.
5. Lettura di digest hash e UUID
Un hash MD5 come d41d8cd98f00b204e9800998ecf8427e è composto da 32 caratteri esadecimali, che rappresentano 16 byte (128 bit). Ogni coppia di cifre esadecimali è un byte.
Un UUID segue il pattern esadecimale 8-4-4-4-12:
550e8400-e29b-41d4-a716-446655440000
Sono 32 cifre esadecimali separate da trattini: gli stessi 128 bit, solo formattati diversamente. Il nibble di versione si trova in posizione 13 (il 4 in 41d4 significa UUID v4).
Genera hash con il nostro Generatore di hash MD5 e SHA o crea UUID con il nostro Generatore UUID: entrambi producono output esadecimale che mappa direttamente alle rappresentazioni binarie discusse qui.
Oltre la base 16: base 36, base 64 e basi personalizzate
Le quattro basi standard coprono la maggior parte del lavoro, ma alcune altre compaiono in contesti specializzati.
Base 36 — Codifica alfanumerica compatta
La base 36 usa tutte le 10 cifre più 26 lettere (A-Z), dandoti la rappresentazione alfanumerica case-insensitive più compatta possibile. Gli URL shortener la adorano: gli ID dei video di YouTube, i link brevi e le chiavi di database compatte usano spesso la base 36.
(1000000).toString(36) // 'lfls'
parseInt('lfls', 36) // 1000000
Il decimale 1.000.000 si comprime a soli quattro caratteri. Per identificatori brevi URL-safe, è difficile fare di meglio.
Base 64 — Codifica di dati (non un sistema numerico)
Base64 sembra un’altra base, ma serve uno scopo diverso. Anziché rappresentare un valore numerico in un sistema posizionale, Base64 codifica dati binari arbitrari (immagini, file, token JWT) come testo ASCII. Usa A-Z, a-z, 0-9, + e /: 64 simboli in totale.
La matematica è diversa dalla conversione di base. Base64 elabora l’input in blocchi da 3 byte (24 bit) e produce in output quattro caratteri da 6 bit. È uno schema di codifica, non un sistema numerale.
Per codificare e decodificare dati Base64, usa il nostro Codificatore e decodificatore Base64.
Basi arbitrarie (2-36) e quando appaiono
Altre basi compaiono in natura:
- Base 12 (dozzinale): tempo (12 ore), quantità (una dozzina). Alcuni matematici sostengono che la base 12 sarebbe migliore della base 10 per l’uso quotidiano perché 12 ha più divisori.
- Base 60 (sessagesimale): tempo (60 secondi, 60 minuti) e angoli (360°). Ereditata dalla matematica babilonese.
- Base 32: la codifica Base32 di Crockford per identificatori leggibili dall’uomo (esclude caratteri ambigui come I, L, O). Usata anche nel geohashing.
Il nostro Convertitore di basi supporta qualsiasi base intera da 2 a 36.
Operazioni bitwise e conversione di base
Comprendere il binario non riguarda solo la conversione di numeri: è la base per le operazioni bitwise che compaiono nella programmazione di sistemi, nello sviluppo di giochi e nei sistemi di permessi.
const READ = 0b100; // 4
const WRITE = 0b010; // 2
const EXEC = 0b001; // 1
// Combina i permessi con OR
const perms = READ | WRITE; // 0b110 = 6
// Verifica un permesso specifico con AND
(perms & READ) !== 0 // true — ha lettura
(perms & EXEC) !== 0 // false — niente esec
// Inverti un permesso con XOR
perms ^ WRITE // 0b100 = 4 — scrittura rimossa
// Operazioni di shift
1 << 3 // 0b1000 = 8 (1 spostato a sinistra di 3)
0xFF >> 4 // 0b00001111 = 15 (shift a destra di 4 = divisione per 16)
Feature flag, registri hardware, protocolli di rete e programmazione grafica si appoggiano tutti alle operazioni bitwise. Una volta che il binario fa clic, la manipolazione dei bit si legge come logica pura, senza magia.
FAQ
Quali sono i quattro sistemi numerici principali usati nella programmazione?
Binario (base 2), ottale (base 8), decimale (base 10) ed esadecimale (base 16). Il binario è come i dati esistono fisicamente nell’hardware. L’ottale mappa ai permessi dei file Unix. Il decimale è il default rivolto all’umano. L’esadecimale comprime il binario in forma leggibile: ogni cifra esadecimale è esattamente 4 bit.
Come converto binario in esadecimale?
Raggruppa le cifre binarie in insiemi di 4 da destra a sinistra, riempiendo il gruppo più a sinistra con zeri se necessario. Mappa ogni gruppo: 0000=0, 0001=1, …, 1010=A, …, 1111=F. Esempio: binario 10101111 → gruppi 1010 1111 → esadecimale AF. Funziona perché 16 = 2⁴.
Come converto esadecimale in decimale?
Moltiplica ogni cifra esadecimale per 16 elevato alla potenza della sua posizione (più a destra = 0), poi somma. A=10, B=11, C=12, D=13, E=14, F=15. Esempio: esadecimale FF = 15×16¹ + 15×16⁰ = 240 + 15 = 255. Nel codice: JavaScript parseInt('FF', 16), Python int('FF', 16).
Perché i programmatori usano l’esadecimale invece del binario?
L’esadecimale è compatto. Ogni cifra esadecimale mappa esattamente a 4 bit, quindi 11111111 00001010 in binario diventa FF0A in esadecimale, molto più corto e facile da scansionare. L’esadecimale è lo standard per indirizzi di memoria, colori CSS (#FF5733), indirizzi MAC, output di hash e formattazione UUID.
Cos’è un nibble e perché conta per la conversione esadecimale?
Un nibble è composto da 4 bit binari, mezzo byte. Un nibble mappa esattamente a una cifra esadecimale, ed è per questo che la conversione binario-esadecimale è solo una lookup nibble per nibble. Un byte = due nibble = due cifre esadecimali. Questa pulita mappatura a 4 bit è la ragione per cui l’esadecimale è diventato lo standard per rappresentare dati a livello di byte.
Perché i permessi dei file Unix sono scritti in ottale?
Tre bit di permesso (lettura=4, scrittura=2, esecuzione=1) per gruppo, tre gruppi (proprietario, gruppo, altri). Poiché 2³ = 8, ogni gruppo di tre bit mappa a una cifra ottale. 755 significa proprietario=7 (rwx), gruppo=5 (r-x), altri=5 (r-x). L’ottale è la base naturale per raggruppamenti di 3 bit.
Come gestisco numeri più grandi di 2⁵³ in JavaScript?
Usa BigInt. Aggiungi n a un letterale o usa il costruttore BigInt(): BigInt('0xFFFFFFFFFFFFFFFF').toString(2) produce la stringa binaria completa a 64 bit. Il Number standard perde precisione oltre 9.007.199.254.740.991 (2⁵³ - 1). Il nostro Convertitore di basi usa internamente BigInt, quindi gestisce numeri di qualsiasi dimensione senza perdita di precisione.
Come converto esadecimale in binario?
Sostituisci ogni cifra esadecimale con il suo equivalente binario a 4 bit, usando la stessa tabella nibble al contrario: 0=0000, 1=0001, …, A=1010, …, F=1111. Esempio: esadecimale AF → A (1010) + F (1111) → binario 10101111. Nel codice: JavaScript parseInt('AF', 16).toString(2) o Python bin(int('AF', 16))[2:].
Perché i colori esadecimali CSS hanno a volte 3, 6 o 8 cifre?
Tutte e tre le forme mappano allo stesso modello RGB ma codificano precisione e alpha diversi. La forma a 3 cifre #F0A è una scorciatoia che si espande a #FF00AA (ogni cifra raddoppiata). La forma a 6 cifre #FF00AA è la forma RGB standard: due cifre esadecimali per canale. La forma a 8 cifre #FF00AA80 aggiunge un canale alpha come quarto byte, dove 80 (decimale 128) è circa il 50% di opacità. I browser moderni accettano tutte e tre; i designer scelgono la forma più corta che preserva l’intento.