Esercizio 27C, resistenza equivalente di un circuito (albero)
In questa pagina 4
Testo (scritto del 24/06/2026, parte 3, in C). Circuiti di resistenze. Svolgi il seguente esercizio sviluppando le funzioni richieste in C. I prototipi delle funzioni non possono essere modificati. Durante l'esame non è possibile consultare appunti o materiale didattico; è consentito utilizzare la documentazione Linux con man.
Un simulatore di circuiti elettrici elementari rappresenta un circuito costituito esclusivamente da resistenze mediante un albero binario proprio. Ogni foglia rappresenta una singola resistenza. Ogni nodo interno rappresenta il collegamento di due sotto-circuiti: il nodo indica se i due sotto-circuiti figli sono collegati in serie oppure in parallelo. Di conseguenza ogni sottoalbero rappresenta un sotto-circuito. Ad esempio un circuito con in serie con il parallelo di ed è rappresentato dall'albero con radice Serie, figlio sinistro e figlio destro Parallelo con figli e . In C:
typedef enum tipo_nodo { RESISTORE, SERIE, PARALLELO } TipoNodo;
typedef struct circuito {
TipoNodo tipo;
double valore;
struct circuito *left;
struct circuito *right;
} Circuito;Per i nodi di tipo RESISTORE, il campo valore contiene la resistenza in ohm e i figli sono NULL. Per i nodi SERIE o PARALLELO, valore non è usato e i figli rappresentano i due sotto-circuiti collegati.
Funzioni da completare:
double combinaResistenze(double a, double b, TipoNodo tipo): restituisce la resistenza equivalente di due blocchi. Per un collegamento in serie vale ; in parallelo .double resistenzaEquivalente(Circuito *root): calcola ricorsivamente la resistenza equivalente dell'intero circuito. Per un puntatoreNULLrestituisce . I test usano circuiti validi, in cui ogni nodo interno ha due figli.int contaResistori(Circuito *root): conta ricorsivamente quante resistenze singole, cioè nodi di tipoRESISTORE, sono presenti nel circuito.
Indicazioni: la visita dell'albero deve essere ricorsiva; si possono definire funzioni ausiliarie; non modificare main() e le funzioni di test; il Makefile collega la libreria matematica con -lm. Esempio: una resistenza da in serie con il parallelo di due resistenze da ha resistenza equivalente : il parallelo vale e il collegamento in serie aggiunge gli altri .
Richiami
Alberi in C e visite ricorsive: Alberi e heap in CAlbero binario in C con nodo struct e figli left/right; funzioni ricorsive (conteggio, altezza, visita inorder, liberazione in postorder); inserimento in un albero binario di ricerca con Nodo **; min-heap su array con indici da 1 (insert, removeMin, bottomUp).Alberi e heap in C →. Le formule fisiche sono quelle di Teoria dei Circuiti (Resistenza equivalente e trasformazione stella-triangoloUna rete di soli resistori passivi vista da due morsetti A e B equivale a un unico resistore R_eq. Si calcola riducendo la rete con serie e parallelo, partendo dalla parte più lontana dai morsetti. Quando serie e parallelo non bastano (ponti), si usa la trasformazione triangolo→stella (R_A = R_AB·R_CA / somma) o stella→triangolo (R_AB = (R_A R_B + R_B R_C + R_C R_A)/R_C). Con tre resistori uguali R_Δ = 3 R_Y.Resistenza equivalente e trasformazione stella-triangolo →, Leggi di Kirchhoff (LKC e LKT)LKC: in ogni istante la somma algebrica delle correnti che attraversano una superficie chiusa (per esempio attorno a un nodo) è zero. LKT: in ogni istante la somma algebrica delle tensioni lungo un percorso chiuso che tocca solo nodi (per esempio una maglia) è zero. Dipendono solo da come sono collegati i componenti.Leggi di Kirchhoff (LKC e LKT) →): in serie le resistenze si sommano, , perché la stessa corrente le attraversa e le tensioni si sommano; in parallelo si sommano le conduttanze, , da cui (si porta a denominatore comune: e si inverte). Valutazione di un albero binario proprio con una visita in postorder: il valore di un nodo interno dipende dai valori dei figli (vedi Alberi binariAlbero binario e albero binario proprio; interfaccia; relazioni tra nodi, foglie e altezza (m = n-m+1, h+1 <= m <= 2^h, 2h+1 <= n <= 2^(h+1)-1) con dimostrazioni; visita inorder; parse tree e valutazione di espressioni; heightSum come esempio di calcolo di un'informazione più ricca.Alberi binari →, analogo alla valutazione di un'espressione).
Soluzione
double combinaResistenze(double a, double b, TipoNodo tipo) {
if (tipo == SERIE)
return a + b;
return (a * b) / (a + b); /* PARALLELO */
}
double resistenzaEquivalente(Circuito *root) {
if (root == NULL)
return 0.0;
if (root->tipo == RESISTORE)
return root->valore;
double a = resistenzaEquivalente(root->left);
double b = resistenzaEquivalente(root->right);
return combinaResistenze(a, b, root->tipo);
}
int contaResistori(Circuito *root) {
if (root == NULL)
return 0;
if (root->tipo == RESISTORE)
return 1;
return contaResistori(root->left) + contaResistori(root->right);
}Traccia di resistenzaEquivalente sull'esempio del testo (radice SERIE, figli: resistenza e PARALLELO con due resistenze da ): la chiamata sulla radice richiama la sinistra, che è un RESISTORE e restituisce ; poi la destra, che richiama le sue due foglie ( e ) e restituisce combinaResistenze(200, 200, PARALLELO) ; infine la radice restituisce combinaResistenze(100, 100, SERIE) . contaResistori conta le tre foglie: .
Struttura. Entrambe le funzioni sono visite ricorsive: caso base NULL (e foglia = RESISTORE), poi si combinano i risultati dei due figli. resistenzaEquivalente è un postorder in cui la "visita" è combinaResistenze. Complessità tempo (una chiamata per nodo) e stack.
Dettagli.
- Per il parallelo divide per zero: nei circuiti dei test le resistenze sono positive, quindi non succede. Con un ramo in cortocircuito () la formula darebbe , corretta.
- Il parallelo di due resistenze è sempre minore della minore delle due: se , cioè sempre per ; in particolare e . Per vale (resistenze uguali in parallelo). Il risultato è un
double, quindi può avere errori di arrotondamento (Numeri in virgola mobile IEEE 754Virgola fissa e virgola mobile; formato IEEE 754 a 32 e 64 bit (segno, esponente in eccesso 127, mantissa con 1 implicito); conversioni svolte nei due versi; valori speciali, denormalizzati, intervallo, precisione e arrotondamento.Numeri in virgola mobile IEEE 754 →), irrilevanti per un test con tolleranza. - Si usano
doublee nonint: in aritmetica intera troncherebbe il risultato. - Si controlla
root->tipoper distinguere foglia e nodo interno, senza guardare i figli: nelle foglie sonoNULL, ma è il tipo a definire il significato del nodo.
Prove eseguite
| Circuito | Resistori | |
|---|---|---|
| una sola resistenza da | ||
albero vuoto (NULL) |
(Controllo: e ; combinaResistenze(3, 6, SERIE) , combinaResistenze(3, 6, PARALLELO) . Provato compilando con gcc -std=c99.)
Errori comuni
- Usare la divisione tra interi (
int a, b) o dimenticare la parentesi in(a * b) / (a + b). - Dimenticare il caso
RESISTOREe richiamarsi ricorsivamente sui figliNULL(non rompe, macombinaResistenzeverrebbe chiamata con tipoRESISTOREe darebbe un risultato errato). - Contare i nodi interni invece delle foglie in
contaResistori: i resistori sono le foglie (in un albero proprio sono , vedi Alberi binariAlbero binario e albero binario proprio; interfaccia; relazioni tra nodi, foglie e altezza (m = n-m+1, h+1 <= m <= 2^h, 2h+1 <= n <= 2^(h+1)-1) con dimostrazioni; visita inorder; parse tree e valutazione di espressioni; heightSum come esempio di calcolo di un'informazione più ricca.Alberi binari →). - Confondere serie e parallelo: la serie somma, il parallelo ha la resistenza equivalente minore di ciascun ramo.
Versione ripasso
Testo. Circuito di resistenze come albero binario proprio (RESISTORE, SERIE, PARALLELO); implementare combinaResistenze(a, b, tipo) (serie , parallelo ), resistenzaEquivalente(Circuito*) (ricorsiva, NULL ) e contaResistori(Circuito*).
- Postorder (vedi Alberi binariAlbero binario e albero binario proprio; interfaccia; relazioni tra nodi, foglie e altezza (m = n-m+1, h+1 <= m <= 2^h, 2h+1 <= n <= 2^(h+1)-1) con dimostrazioni; visita inorder; parse tree e valutazione di espressioni; heightSum come esempio di calcolo di un'informazione più ricca.Alberi binari →):
NULL⇒ ;RESISTORE⇒valore(o nel conteggio); altrimenti si combinano i valori dei due figli concombinaResistenze. - Codice:
combinaResistenze:tipo == SERIE ? a + b : (a * b) / (a + b);contaResistori: somma dei due figli. - Complessità: , stack (vedi Alberi e heap in CAlbero binario in C con nodo struct e figli left/right; funzioni ricorsive (conteggio, altezza, visita inorder, liberazione in postorder); inserimento in un albero binario di ricerca con Nodo **; min-heap su array con indici da 1 (insert, removeMin, bottomUp).Alberi e heap in C →).
- Prove: (3 resistori); ; una resistenza ⇒ , ;
NULL⇒ , . - Codice:
combinaResistenze:tipo == SERIE ? a + b : (a * b) / (a + b);resistenzaEquivalente:NULL,RESISTOREvalore, altrimenticombinaResistenze(eq(left), eq(right), tipo);contaResistori:NULL,RESISTORE, altrimenti somma dei figli. - Controllo: , .
- Dettagli:
doublee nonint(la divisione intera tronca); si distingue foglia e nodo interno dal campotipo; parallelo con non compare nei test (resistenze positive). - Errori: divisione tra interi; caso
RESISTOREomesso; contare i nodi interni; serie e parallelo scambiati.