Vai al contenuto
Topos Uranos

Riepilogo

Un’espressione aritmetica non si calcola da sinistra a destra come si legge, ma secondo una struttura nascosta, il suo albero, che è fissata dalla precedenza degli operatori, dalla loro associatività e dalle parentesi; e in ogni nodo di quell’albero il tipo degli operandi decide quale operazione si esegue, di modo che 7 / 2 vale 3 e 7 / 2.0 vale 3.5. Questa lezione studia i cinque operatori aritmetici di C++ con interi e con reali; la divisione intera e il resto, che da C++11 troncano verso lo zero, da cui segue che il resto prende il segno del dividendo e differisce dal resto della divisione euclidea quando il dividendo è negativo; il modo di ottenere il resto euclideo; l’albero di un’espressione; il tipo del risultato quando gli operandi sono di tipi diversi, e i due modi in cui un’espressione aritmetica intera perde il suo significato: dividere per zero e andare in overflow in un calcolo intermedio.

Obiettivi di apprendimento

  1. Calcolare il quoziente e il resto della divisione intera in C++, anche con operandi negativi, e metterli in relazione con il quoziente e il resto della divisione euclidea.
  2. Disegnare l’albero di un’espressione aritmetica secondo la precedenza e l’associatività, e calcolarne il valore.
  3. Prevedere il tipo del risultato di un’operazione tra operandi di tipi diversi.
  4. Usare la divisione intera e il resto per scomporre quantità: le cifre di un numero, una durata in ore e minuti, un giorno della settimana.

Gli operatori aritmetici

C++ ha cinque operatori aritmetici binari: la somma +, la sottrazione -, il prodotto *, la divisione / e il resto %; ha inoltre il meno unario, che cambia il segno del suo unico operando, come in -x, e un più unario, +x, che lo lascia com’è. I primi quattro si applicano agli interi e ai reali; il resto, solo agli interi. Ora, la stessa scrittura non designa la stessa operazione in tutti i casi: se i due operandi di / sono interi, la divisione è intera e il suo risultato è un intero, il quoziente senza la parte frazionaria; se uno dei due è reale, la divisione è reale. La lezione Caratteri, booleani, conversioni e costanti ha mostrato la conseguenza più visibile di questa regola, cioè che double r{7 / 2}; memorizza 3: la divisione è stata fatta tra interi prima che il risultato fosse convertito in reale.

EsempioI cinque operatori con due interi

Il programma applica i cinque operatori a 17 e 5, e ripete la divisione con un dividendo reale.

Programma in C++
#include <print>​int main(){    const int a{17};    const int b{5};    std::println("{} + {} = {}", a, b, a + b);    std::println("{} - {} = {}", a, b, a - b);    std::println("{} * {} = {}", a, b, a * b);    std::println("{} / {} = {}", a, b, a / b);    std::println("{} % {} = {}", a, b, a % b);    const double x{17.0};    std::println("{} / {} = {}", x, b, x / b);}
Output
17 + 5 = 2217 - 5 = 1217 * 5 = 8517 / 5 = 317 % 5 = 217 / 5 = 3.4

17 diviso 5 dà 3 con il resto di 2: sono il quoziente e il resto della ripartizione di 17 oggetti in gruppi di 5. L’ultima riga divide un reale per un intero e ottiene 3.4. Va notato che std::println scrive il reale 17.0 come «17»: il segnaposto vuoto scrive la rappresentazione più breve del valore, di modo che ciò che si scrive non rivela il tipo; per vederlo, si chiedono decimali con {:.1f}.

L’operatore % non ammette reali. Scrivere 7.5 % 2 non è un errore di logica che il programma scopra durante l’esecuzione, ma un errore di compilazione: il compilatore dice che gli operandi di tipo double e int non sono validi per l’operatore.

Programma in C++
#include <print>​int main(){    std::println("{}", 7.5 % 2);}
Messaggi di errore del compilatore
main.cpp: In function ‘int main()’:main.cpp:5:28: error: invalid operands of types ‘double’ and ‘int’ to binary ‘operator%’    5 |     std::println("{}", 7.5 % 2);      |                        ~~~ ^ ~

Il resto di una divisione reale esiste, e lo calcola la funzione std::fmod dell’header <cmath>, che si studierà nella lezione Bit e libreria matematica, insieme alla potenza: C++ non ha un operatore di potenza, e 2 ^ 3 non vale 8, ma un’altra cosa che sarà spiegata lì.