Lezione 5 di 7 · 20 min di lettura

Fare i conti

Somme, divisioni (con una trappola celebre), confronti e logica. E le regole di precedenza che C3 ha riscritto.

Il computer è una calcolatrice molto pignola

Un operatore è un simbolo che combina dei valori per produrne uno nuovo: + prende due numeri e ne dà la somma. L’espressione 2 + 3 vale 5, e puoi usarla ovunque potresti usare un 5: in un’assegnazione, come argomento di una funzione, dentro un’altra espressione.

conti.c3
import std::io;

fn void main()
{
	int a = 7;
	int b = 2;

	io::printn(a + b);   // somma
	io::printn(a - b);   // sottrazione
	io::printn(a * b);   // moltiplicazione
	io::printn(a / b);   // divisione... con sorpresa
	io::printn(a % b);   // resto della divisione
}
output
9
5
14
3
1

Quattro su cinque sono quelle che ti aspetti. La quarta merita un paragrafo tutto suo.

La trappola della divisione intera

7 / 2 fa 3. Non 3,5. Non arrotondato: troncato, cioè con la parte decimale semplicemente buttata via. Perché? Perché entrambi i numeri sono int, e il risultato di un’operazione tra interi è un intero. Il compilatore non “vede” che avresti voluto un decimale.

Se vuoi 3,5, almeno uno dei due deve essere un decimale:

c3
io::printn(7.0 / 2);       // 3.500000: 7.0 è un double
int a = 7;
io::printn(a / 2.0);       // 3.500000: 2.0 è un double
io::printn((double)a / 2); // 3.500000: converto a esplicitamente
double d = a / 2;
io::printn(d);             // 3.000000!! la divisione avviene PRIMA, tra interi

L’ultimo caso è il più insidioso: d è un double, ma a / 2 viene calcolato tra due int (fa 3) e solo dopo il 3 viene messo nella scatola double. Il danno è già fatto.

✏️ Quiz

Cosa stampa io::printn(9 / 2 * 2);?

Il resto: %

L’operatore % (si legge “modulo”) dà il resto della divisione intera. 17 % 5 fa 2, perché 17 = 5 × 3 + 2. Sembra un’operazione da scuola elementare, e invece è tra le più usate in programmazione:

c3
int minuti = 135;
io::printfn("%d ore e %d minuti", minuti / 60, minuti % 60);
output
2 ore e 15 minuti

E il classico dei classici: un numero è pari se il resto della divisione per 2 è zero.

c3
int n = 7;
io::printn(n % 2 == 0);
output
false

(Quel == è un confronto: ci arriviamo tra un attimo.)

Modificare una variabile “in posto”

Scrivere x = x + 5 è così comune che esiste una scorciatoia:

Forma lungaForma corta
x = x + 5;x += 5;
x = x - 5;x -= 5;
x = x * 2;x *= 2;
x = x / 2;x /= 2;
x = x % 2;x %= 2;
x = x + 1;x++;
x = x - 1;x--;
c3
int x = 10;
x += 5;   // 15
x++;      // 16
x *= 2;   // 32
x--;      // 31
io::printn(x);
output
31

Quando i numeri traboccano

Un int arriva a 2 147 483 647. Cosa succede se aggiungi 1?

c3
int m = 2_147_483_647;
m++;
io::printn(m);
output
-2147483648

Il numero “gira” e ricomincia dal fondo, come un contachilometri che dopo 999999 torna a 000000. Si chiama overflow (trabocco), e in C3 è un comportamento definito: succede sempre così, su ogni macchina (in C, per gli interi con segno, è ufficialmente “comportamento indefinito”, cioè può succedere qualsiasi cosa). Definito non vuol dire innocuo: se stai contando i soldi di una banca e il conto diventa negativo, hai un problema. Quando i numeri possono crescere molto, usa long.

Confronti: domande con risposta sì o no

Un confronto mette a paragone due valori e produce un bool:

OperatoreSignificatoEsempioVale
==uguale a5 == 5true
!=diverso da5 != 5false
<minore di3 < 2false
>maggiore di3 > 2true
<=minore o uguale2 <= 2true
>=maggiore o uguale1 >= 2false
c3
int eta = 20;
bool maggiorenne = eta >= 18;
io::printn(maggiorenne);
output
true

Logica: combinare le domande

Con i operatori logici metti insieme più condizioni:

OperatoreNomeVale true quando…
&&AND (e)entrambe le condizioni sono vere
\|\|OR (o)almeno una è vera
!NOT (non)la condizione è falsa (la inverte)
c3
int eta = 20;
bool ha_biglietto = false;

io::printn(eta >= 18 && ha_biglietto);   // entra al concerto?
io::printn(eta >= 18 || ha_biglietto);   // basta una delle due?
io::printn(!ha_biglietto);               // NON ha il biglietto?
output
false
true
true

✏️ Quiz

Con int a = 5; e int b = 10;, quanto vale a * 2 == b && b / a == 2?

Precedenza: chi va per primo

2 + 3 * 4 fa 14, non 20, perché la moltiplicazione ha la precedenza sulla somma, come a scuola. E 10 - 4 - 3 fa 3, perché a parità di precedenza si va da sinistra a destra.

L’ordine in C3, dal più forte al più debole (semplificato ai casi che ti servono ora):

  1. () parentesi, e le chiamate di funzione
  2. !, - davanti a un numero (negazione)
  3. *, /, %
  4. <<, >> (spostamenti di bit)
  5. &, |, ^ (operazioni sui bit)
  6. +, -
  7. ==, !=, <, >, <=, >=
  8. &&
  9. ||
  10. =, +=, ecc.

Quando hai un dubbio, metti le parentesi. Non costano niente, e chi legge ti ringrazia.

Un programma vero

Mettiamo tutto insieme con un piccolo calcolo utile: quanto costa un viaggio in auto?

viaggio.c3
import std::io;

const double PREZZO_BENZINA = 1.85;  // euro al litro

fn void main()
{
	int km = 320;
	double consumo = 6.5;   // litri ogni 100 km
	int passeggeri = 4;

	double litri = km / 100.0 * consumo;
	double costo = litri * PREZZO_BENZINA;
	double a_testa = costo / passeggeri;

	io::printn(litri);
	io::printn(costo);
	io::printn(a_testa);
	io::printn(a_testa < 10.0);
}
output
20.800000
38.480000
9.620000
true

Nota km / 100.0: ho scritto 100.0 e non 100 apposta, per evitare la divisione intera (con 100 avrei ottenuto 3, non 3,2). E costo / passeggeri è sicuro perché costo è già un double.

🛠️ Esercizio · sul tuo computer

Il resto della spesa

Scrivi un programma spesa.c3 con:

  • int budget = 50;
  • int prezzo = 12;

Poi stampa, una per riga con io::printn:

  1. quanti oggetti da prezzo euro puoi comprare con budget (divisione intera);
  2. quanti euro ti restano dopo averli comprati (il resto);
  3. se ti restano abbastanza soldi per comprarne un altro (resto >= prezzo);
  4. se il budget è un numero pari.

Puoi usare variabili intermedie o scrivere le espressioni direttamente dentro printn. Riporta l’output.

🔒 Mostra una soluzione (prima prova da solo!)
spesa.c3
import std::io;

fn void main()
{
	int budget = 50;
	int prezzo = 12;

	int quanti = budget / prezzo;
	int resto = budget % prezzo;

	io::printn(quanti);
	io::printn(resto);
	io::printn(resto >= prezzo);
	io::printn(budget % 2 == 0);
}

Ricapitolando

  • + - * / % sui numeri. Tra interi, / tronca e % dà il resto.
  • Per una divisione decimale, almeno un operando deve essere double.
  • +=, -=, *=, ++, -- modificano la variabile in posto.
  • Gli interi traboccano “girando”: per numeri grandi usa long.
  • Confronti (== != < > <= >=) producono un bool; == chiede, = ordina.
  • &&, ||, ! combinano i bool. && e || sono pigri.
  • In C3 gli operatori sui bit vengono prima di +/-. Nel dubbio: parentesi.

Prossima lezione: finora abbiamo stampato una cosa per riga. È ora di imparare a formattare l’output come si deve.

Corso non ufficiale · basato sulla documentazione di c3-lang.org · aggiornato al 2026