Maurizio Tomasi (maurizio.tomasi@unimi.it
)
Martedì 14 Ottobre 2025
La spiegazione dettagliata degli esercizi si trova qui: carminati-esercizi-04.html.
Come al solito, queste slides, che forniscono suggerimenti addizionali rispetto alla lezione di teoria, sono disponibili all’indirizzo ziotom78.github.io/tnds-tomasi-notebooks.
L’esercizio richiede di calcolare la media e la deviazione standard usando una stride, ossia considerando solo un elemento ogni N nel vettore.
È un metodo molto usato nelle serie temporali, dove valori consecutivi hanno una correlazione significativa che invaliderebbe l’uso della media e della deviazione standard tout court.
Il mio testo dell’Esercizio 4.0 contiene alcune indicazioni in più;
In particolare, contiene il codice per verificare la correttezza delle nuove funzioni statistiche:
void test_statistics_with_stride() {
vector<double> v{1.0, 2.0, 3.0, 4.0, 5.0, 6.0};
assert(are_close(mean(v, 1), 3.5));
assert(are_close(mean(v, 2), 3.0));
assert(are_close(mean(v, 3), 2.5));
assert(are_close(stddev(v, 1), 1.707825127659933));
assert(are_close(stddev(v, 2), 1.632993161855452));
assert(are_close(stddev(v, 3), 1.5));
println(cerr, "All the tests have passed. Hurrah! 🥳");
}
Sin dal 2020 lo standard C++ include una libreria per la formattazione di stringhe
Avete usato questa libreria tutte le volte che avete invocato
std::print()
o std::println()
, ma non abbiamo
mai approfondito il funzionamento: sappiamo solo che quando mettiamo
{}
si può stampare il valore di una variabile
Oggi approfondiremo queste funzionalità, che si ispirano ad altri linguaggi come Python, C# e Rust
std::print
Le funzioni print()
e println()
usano
{}
al posto di ____
:
Si può fare riferimento alle variabili usando il loro indice:
Inoltre print
e println
, a differenza
di cout <<
, stampano correttamente caratteri come i
simboli (±
), le emoji e le lettere accentate anche in
Windows.
È possibile specificare il modo in cui un valore va scritto
inserendo degli argomenti dentro {}
dopo i due punti
(:
). Ad esempio, per formattare numeri floating-point con 2
cifre dopo la virgola si scrive {:.2f}
Se si vuole usare la notazione scientifica, si usa la lettera
e
. Ad esempio, la scrittura {:.5e}
indica che
si richiedono 5 cifre dopo la virgola
Si può indicare il numero di caratteri da usare inserendo subito
dopo :
un numero: {:5}
chiede di usare almeno
5 caratteri per scrivere il valore. Questo è utile per allineare i campi
nelle tabelle.
È possibile mettere insieme l’indice (0
), l’ampiezza
(5
) e il numero di cifre dopo la virgola (.2
)
scrivendoli uno dopo l’altro: {0:5.2e}
.
Capita che il numero di cifre da usare per stampare un numero non sia noto a priori, ma vada calcolato nel programma
Questo esempio usa digits
per specificare il numero
di cifre:
double error{0.001};
double value{1.42145};
int digits{-static_cast<int>(log10(error))};
// #0 #1 #2
println("The result is {0:.{2}f} ± {1:.{2}f}", value, error, digits);
// Output: "The result is 1.421 ± 0.001"
La scrittura .{2}f
indica: “formatta il numero come un
floating-point, e metti dopo il punto tante cifre quante sono nel
parametro #2”
Le funzioni print
e println
stampano
stringhe a video o in un file, sostituendo {}
con valori di
variabili
Ci sono però situazioni in cui questa funzionalità serve per passare stringhe ad altre funzioni, e non per stamparle
Ad esempio, potreste voler salvare un grafico e usare la
sostituzione {}
nel titolo: in tal caso la stringa va
passata a una funzione della libreria grafica
Questo è possibile con std::format()
, che
restituisce una stringa formattata (includete
<format>
:
Nelle lezioni precedenti avete visto come usare ROOT per produrre grafici.
Nel laboratorio di TNDS, ROOT è usato come libreria C++, ossia come un insieme di classi invocabili all’interno dei vostri programmi.
Un’alternativa a ROOT è Gnuplot:
Ho sviluppato una libreria C++ che invoca Gnuplot all’interno di programmi C++. È disponibile all’indirizzo github.com/ziotom78/gplotpp.
È più veloce di ROOT, occupa pochissimo, non richiede installazioni complesse e funziona bene con VSCode. Inoltre funziona anche sotto Windows, se prima installate Gnuplot nel modo giusto.
Sui vostri laptop dovete scaricare il file gplot++.h nella cartella dove vi serve (da ripetere per ogni cartella!), oppure eseguite (sotto Linux/Mac OS X):
Basta poi scrivere #include "gplot++.h"
per
usarla.
Visual Studio Code è in grado di visualizzare finestre di aiuto, se spostate il mouse sui comandi di plot (vedi immagine precedente);
Si possono passare direttamente array di vettori di tipo
std::vector
, invece di chiamare ripetutamente
TGraph::SetPoint
;
Non serve cambiare i Makefile
per invocare
root-config
;
Se lavorate sui vostri computer, non serve ricordarsi di eseguire
source root/bin/thisroot.sh
;
Bisogna installarlo dentro ogni cartella che contiene un esercizio, ma occupa appena 9 KB.
L’esempio precedente apre una finestra. Questa soluzione è comoda perché la finestra è «navigabile»: si può zoomare con il mouse come si fa in ROOT!
Per maggiore praticità è però meglio che salviate i plot in file PNG, che sono apribili direttamente in Visual Studio Code.
È sufficiente usare il metodo
Gnuplot::redirect_to_png
subito dopo aver creato una
variabile di tipo Gnuplot
:
int main(void) {
Gnuplot plt{};
std::vector<double> x{1, 2, 3, 4, 5}, y{5, 2, 4, 1, 3};
plt.multiplot(2, 1, "Title"); // Two plots in two rows
plt.set_xlabel("X axis");
plt.set_ylabel("Y axis");
plt.plot(x, y, "x-y plot");
plt.plot(y, x, "y-x plot", Gnuplot::LineStyle::LINESPOINTS);
plt.show(); // Create the plot and move to the next row
plt.set_xlabel("Value");
plt.set_ylabel("Number of counts");
plt.histogram(y, 2, "Histogram"); // Two bins
plt.set_xrange(-1, 7);
plt.set_yrange(0, 5);
plt.show(); // Finalize the figure
}
Per esempi e documentazione, andate alla pagina github.com/ziotom78/gplotpp.