Salta al contenuto
Note per Studenti Esercizio 3 · calcolo di y = a·x + b e di un polinomio in virgola fissa a 32 bit (temi d'esame gennaio 2026 e settembre 2026)

Esercizio 3calcolo di y = a·x + b e di un polinomio in virgola fissa a 32 bit (temi d'esame gennaio 2026 e settembre 2026)

Esame
In questa pagina 4

Testo (tema d'esame gennaio 2026, problema P1; settembre 2026, problema 7).

(i) Determinare il valore di y=a⋅x+by=a\cdot x+b con a=0,35a=0{,}35, x=−2,725x=-2{,}725, b=1,52b=1{,}52. Il calcolo si esegue a virgola fissa su una ALU a 32 bit, con dati a 16 bit in una codifica frazionaria n.mn.m con segno (SS) o senza (UU) scelta in modo da minimizzare l'errore di rappresentazione. Indicare per a,x,b,ya,x,b,y il codice esadecimale e il formato, l'errore assoluto su yy e scrivere un'assegnazione in C per yy.

(ii) Un programmatore calcola sin⁡x≈a x−b x3+c x5\sin x\approx a\,x-b\,x^3+c\,x^5 per x∈[0,π2]x\in[0,\frac\pi2] con a=1a=1, b=16b=\frac16, c=1120c=\frac1{120} in aritmetica a 32 bit. (a) Valori di bb e cc in formato 0.16 U con arrotondamento ed errori; (b) il valore reale di xx e la rappresentazione interna in 1.15 U per x=60∘x=60^\circ; (c) il valore di yy calcolato in 0.16 e l'errore.


Teoria usata: Operazioni in virgola fissa - somma, prodotto e riallineamentoIn virgola fissa il processore opera sugli interi e non sa dov'è la virgola: tocca al programmatore. Regola 1: si sommano solo dati con lo stesso formato (stesso $m$). Regola 2: il prodotto di $n_1.m_1$ per $n_2.m_2$ ha $m_1+m_2$ bit frazionari e il doppio dei bit: va riallineato con uno shift a destra di $m_2$ posizioni (per riportarlo a $m_1$) o preso dalla parte alta. Con la normalizzazione frazionaria $1.15$ il prodotto è $2.30$ e basta uno shift a sinistra di 1 prima di prendere la parte alta. I fattori di scala si scelgono per evitare overflow e perdita di risoluzione.Operazioni in virgola fissa - somma, prodotto e riallineamento →, Rappresentare un valore reale in virgola fissa - formato ottimo ed errorePer rappresentare un reale $x$ su $W$ bit a virgola fissa si sceglie il formato che minimizza l'erroresceglie la rappresentazione per cui la differenza tra il valore rappresentato e quello vero è la più piccola possibile: il maggior numero di bit frazionari $m$ compatibile con l'intervallo ($n=W-m$ bit interi, con U se $x\ge0$, con S se $x<0$). Poi $C=\mathrm{round}(x\cdot2^m)$, scritto in esadecimale (per un negativo, in complemento a 2), e l'errore $\varepsilon=\frac{C}{2^m}-x$, positivo se in eccesso, ha modulo $\le2^{-(m+1)}$. Se invece è dato l'errore massimo, i bit minimi si ricavano da $2^{-(m+1)}\le\varepsilon_{max}$.Rappresentare un valore reale in virgola fissa - formato ottimo ed errore →, Realizzare un filtro o un regolatore a virgola fissaRealizzare in C un filtro a virgola fissa vuol dire scegliere per ogni dato il formato (coefficienti $<1$ in 0.16 U, coefficienti $>1$ in 1.15, 4.12, 5.11 S...), moltiplicare con aritmetica a 32 bit ($16\times16\to32$) e riportare il prodotto al formato di arrivo con uno shift a destrascorrimento dei bit verso destra: equivale a dividere per una potenza di 2; per sommare due prodotti con scale diverse si fa lo shift prima di sommare. Con $a+b=2^{16}$ il filtro $y=\big(a,y_{k-1}+b,(u\ll4)\big)\gg16$ non va in overflow in un uint32_t. Nel codice il formato di ogni variabile va dichiarato in un commento; la funzione $\sin x\approx x-\frac{x^3}6+\frac{x^5}{120}$ mostra come si approssima una funzione con polinomi a coefficienti in virgola fissa.Realizzare un filtro o un regolatore a virgola fissa →.

(i) Formati e codici

Si sceglie per ciascun dato il formato con il massimo numero di bit frazionari che contiene il valore:

  • a=0,35a=0{,}35: positivo, minore di 1: 0.16 U, Ca=round(0,35⋅65536)=22938=0x599AC_a=\mathrm{round}(0{,}35\cdot65536)=22938=\texttt{0x599A} (ε=+6,1⋅10−6\varepsilon=+6{,}1\cdot10^{-6});
  • x=−2,725x=-2{,}725: negativo, ∣x∣<4|x|<4: 3.13 S (segno + 2 bit interi + 13 frazionari), Cx=round(−2,725⋅8192)=−22323→65536−22323=43213=0xA8CDC_x=\mathrm{round}(-2{,}725\cdot8192)=-22323\to65536-22323=43213=\texttt{0xA8CD} (ε=+2,4⋅10−5\varepsilon=+2{,}4\cdot10^{-5});
  • b=1,52b=1{,}52: positivo, tra 1 e 2: 1.15 U, Cb=round(1,52⋅32768)=49807=0xC28FC_b=\mathrm{round}(1{,}52\cdot32768)=49807=\texttt{0xC28F} (ε=−1,1⋅10−5\varepsilon=-1{,}1\cdot10^{-5});
  • yy: il valore atteso è 0,35⋅(−2,725)+1,52=−0,95375+1,52=0,566250{,}35\cdot(-2{,}725)+1{,}52=-0{,}95375+1{,}52=0{,}56625: positivo e minore di 1: 0.16 U.

Riallineamento del calcolo

Il prodotto a⋅xa\cdot x ha 16+13=2916+13=29 bit frazionari. Per sommare bb (15 bit frazionari) i due addendi devono avere lo stesso numero di bit frazionari: si sposta bb a sinistra di 14 posti (29 bit frazionari). La somma ha 29 bit frazionari; per ottenere yy in 0.16 U (16 bit frazionari) si sposta a destra di 13: y16=(Ca⋅Cx+(Cb≪14))≫13.y_{16}=\big(C_a\cdot C_x+(C_b\ll14)\big)\gg13 . Controllo di non overflow su 32 bit con segno: ∣CaCx∣≤65535⋅32768=2,147⋅109<231|C_aC_x|\le65535\cdot32768=2{,}147\cdot10^9<2^{31}; Cb≪14=816 037 888C_b\ll14=816\,037\,888; la somma è 303 992 914<231303\,992\,914<2^{31} ✓.

Numeri: CaCx=22938⋅(−22323)=−512 044 974C_aC_x=22938\cdot(-22323)=-512\,044\,974; Cb≪14=49807⋅16384=816 037 888C_b\ll14=49807\cdot16384=816\,037\,888; somma =303 992 914=303\,992\,914 (a 29 bit frazionari vale 0,566230{,}56623); ≫13\gg13: y16=37108=0x90F4y_{16}=37108=\texttt{0x90F4}, cioè 37108/65536=0,56622337108/65536=0{,}566223.

Errore assoluto su yy: ∣0,566223−0,56625∣=2,7⋅10−5|0{,}566223-0{,}56625|=\mathbf{2{,}7\cdot10^{-5}} (dovuto ai tre arrotondamenti dei dati e al troncamento dello shift finale).

In C (con uint16_t a16=0x599A; int16_t x16=(int16_t)0xA8CD; uint16_t b16=0xC28F;):

c
y16 = (uint16_t)( ( (int32_t)a16 * (int32_t)x16 + ((int32_t)b16 << 14) ) >> 13 );   // y in 0.16 U

Notare i cast a int32_t prima del prodotto (per evitare l'overflow di int a 16 bit e perché x16 è con segno) e che lo shift a destra di un intero con segno è aritmetico.

Dato Formato Codice Errore
a=0,35a=0{,}35 0.16 U 0x599A\texttt{0x599A} +6,1⋅10−6+6{,}1\cdot10^{-6}
x=−2,725x=-2{,}725 3.13 S 0xA8CD\texttt{0xA8CD} +2,4⋅10−5+2{,}4\cdot10^{-5}
b=1,52b=1{,}52 1.15 U 0xC28F\texttt{0xC28F} −1,1⋅10−5-1{,}1\cdot10^{-5}
y=0,56625y=0{,}56625 0.16 U 0x90F4\texttt{0x90F4} −2,7⋅10−5-2{,}7\cdot10^{-5}

(ii) Polinomio per il seno

(a) Coefficienti in 0.16 U con arrotondamento: b=16=0,166667b=\frac16=0{,}166667: round(10922,67)=10923=0x2AAB\mathrm{round}(10922{,}67)=10923=\texttt{0x2AAB}, ε=+5,1⋅10−6\varepsilon=+5{,}1\cdot10^{-6}; c=1120=0,008333c=\frac1{120}=0{,}008333: round(546,13)=546=0x0222\mathrm{round}(546{,}13)=546=\texttt{0x0222}, ε=−2,0⋅10−6\varepsilon=-2{,}0\cdot10^{-6}. (a=1a=1 non è rappresentabile in 0.16 U: si tratta come xx stesso, senza moltiplicazione.)

(b) Il valore di xx. x=60∘=π3=1,047198x=60^\circ=\frac\pi3=1{,}047198 rad, in 1.15 U (x∈[0,2)x\in[0,2)): Cx=round(1,047198⋅32768)=34315=0x860BC_x=\mathrm{round}(1{,}047198\cdot32768)=34315=\texttt{0x860B}; il valore realmente usato è 3431532768=1,047211\frac{34315}{32768}=\mathbf{1{,}047211} (errore +1,3⋅10−5+1{,}3\cdot10^{-5}).

(c) Il valore calcolato. Il polinomio con coefficienti esatti calcolato in x=1,047211x=1{,}047211 dà yvero=1,047211−0,191404+0,010495=0,866302y_{vero}=1{,}047211-0{,}191404+0{,}010495=0{,}866302. Il processore calcola: x2=(CxCx)≫15x^2=(C_xC_x)\gg15, x3=(x2Cx)≫15x^3=(x^2C_x)\gg15, x5=(x3x2)≫15x^5=(x^3x^2)\gg15 (tutti in 1.15); poi y=(Cx≪1)−(Cb x3≫15)+(Cc x5≫15)y=(C_x\ll1)-(C_b\,x^3\gg15)+(C_c\,x^5\gg15) in formato 0.16 U (i prodotti 0.16⋅1.150.16\cdot1.15 hanno 31 bit frazionari: si scartano 15 bit; Cx≪1C_x\ll1 converte 1.15 in 0.16 U). Risultato: y16=0xDDC5=0,866287y_{16}=\texttt{0xDDC5}=0{,}866287; errore rispetto a yveroy_{vero}: −1,5⋅10−5-1{,}5\cdot10^{-5}. Rispetto a sin⁡60∘=0,866025\sin60^\circ=0{,}866025 l'errore è +2,6⋅10−4+2{,}6\cdot10^{-4}: è dominato dall'errore di troncamento della serie di Taylor (ordine 5), non dalla rappresentazione.

Errori comuni

  • Usare per x=−2,725x=-2{,}725 il formato 2.14 S (non contiene −2,725-2{,}725, intervallo [−2,2)[-2,2)).
  • Sommare a⋅xa\cdot x (29 bit frazionari) e bb (15) senza riallineare.
  • Fare il prodotto in 16 bit (uint16_t*int16_t è promosso a int che può andare bene su ARM a 32 bit, ma il risultato va riportato con shift; con tipi più corti si perde il segno).
  • Dimenticare che il risultato dello shift su un intero negativo va ottenuto con shift aritmetico.

Versione ripasso

Testo. y=0,35 x+1,52y=0{,}35\,x+1{,}52 con x=−2,725x=-2{,}725 in virgola fissa a 32 bit (16 bit per dato, formati ottimi); sin⁡x≈x−x36+x5120\sin x\approx x-\frac{x^3}6+\frac{x^5}{120} con coefficienti in 0.16 U (gennaio e settembre 2026).

Teoria collegata