Tema 5: Coma flotant
23.1 Representació IEEE 754
Enunciat: Problema 14.1.
Es treballa amb A = 0x407302B3 i B = 0xF9C40513.
a) Com a naturals
Conversió directa hexadecimal → decimal:
\[A = \texttt{0x407302B3} = 4 \cdot 16^7 + 0 \cdot 16^6 + \cdots = 1\,081\,279\,155\]
\[B = \texttt{0xF9C40513} = 15 \cdot 16^7 + 9 \cdot 16^6 + \cdots = 4\,190\,373\,139\]
b) Com a enters en complement a 2
El bit de signe és el bit 31, que correspon al dígit hexadecimal de més pes.
A = 0x407302B3: quartet de més pes 4 = 0100 → bit 31 = 0 → valor positiu; coincideix amb el natural:
\[A = +1\,081\,279\,155\]
B = 0xF9C40513: quartet de més pes F = 1111 → bit 31 = 1 → valor negatiu. Per obtenir el valor absolut, s’inverteixen tots els bits i se suma 1:
\[\overline{\texttt{0xF9C40513}} + 1 = \texttt{0x063BFAED} = 104\,594\,157\]
\[B = -104\,594\,157\]
c) Com a nombres en coma flotant IEEE 754 de precisió simple
Es descompon cada valor en camps \(S\) (bit 31), \(E_u\) (bits 30:23) i \(F\) (bits 22:0):
Càlcul A = 0x407302B3
Càlcul B = 0xF9C40513
Per a A (\(e = 1\), es desplaça la coma 1 posició a la dreta):
\[A = +11{,}1100\,1100\,0000\,1010\,1100\,11_2\]
\[= 2 + 1 + 2^{-1} + 2^{-2} + \ldots \approx \mathbf{3{,}797}\]
Per a B (\(e = 116\), valor molt gran en mòdul):
\[B \approx -1{,}531 \times 2^{116} \approx \mathbf{-1{,}272 \times 10^{35}}\]
d) Com a instruccions RISC-V
S’identifica l’opcode (bits 6:0) i es descodifica el format:
Càlcul A = 0x407302B3
\[\boxed{A: \texttt{sub t0, t1, t2}}\]
Càlcul B = 0xF9C40513
\[\boxed{B: \texttt{addi a0, s0, -100}}\]
Atenció: el mateix patró de 32 bits representa quatre coses completament diferents: un natural, un enter, un nombre en coma flotant i una instrucció de màquina. El maquinari no distingeix entre elles: és el programari (compilador, sistema operatiu) qui decideix com s’interpreta cada zona de memòria.
Enunciat: Problema 14.3.
La classificació només depèn dels camps \(E\) (exponent) i \(F\) (fracció), segons les codificacions especials (Secció 5.1.6):
| \(E\) | \(F\) | Tipus |
|---|---|---|
0000 0000 |
\(= 0\) | zero (\(\pm 0\), segons el signe) |
0000 0000 |
\(\neq 0\) | subnormal |
1111 1111 |
\(= 0\) | infinit (\(\pm\infty\), segons el signe) |
1111 1111 |
\(\neq 0\) | NaN |
| qualsevol altre | qualsevol | normalitzat |
Aplicant aquestes regles a cada fila:
| Signe | Exponent | Fracció | NRM | DNRM | 0 | INF | NaN |
|---|---|---|---|---|---|---|---|
| 0 | 0000 0000 |
110 0010 0000 1110 1110 1011 |
X | ||||
| 0 | 0000 0000 |
000 0000 0000 0000 0000 0000 |
X | ||||
| 0 | 0010 0100 |
000 0000 0000 0000 0000 0000 |
X | ||||
| 1 | 1111 1111 |
000 0000 0000 0000 0000 0000 |
X | ||||
| 0 | 0010 0100 |
110 0010 0000 1110 1110 1011 |
X | ||||
| 1 | 0000 0000 |
000 0000 0000 0000 0000 0000 |
X | ||||
| 0 | 1111 1111 |
101 0001 0001 0000 1001 0100 |
X |
Observacions:
- Files 1 i 2: amb \(E = 0\), el que distingeix el zero del subnormal és la fracció (\(F = 0\) → zero; \(F \neq 0\) → subnormal).
- Fila 3: \(F = 0\) amb exponent normalitzat (\(E = 0010\,0100_2 = 36\)) és un nombre normalitzat vàlid: la potència de 2 exacta \(+1{,}0 \times 2^{36-127} = 2^{-91}\) (Essencial 5.5).
- Files 4 i 7: amb \(E = 255\), la fracció distingeix l’infinit (\(F = 0\)) del NaN (\(F \neq 0\)).
- Fila 6: el zero té signe: aquesta fila codifica \(-0\).
Enunciat: Problema 14.4.
a) Nombre positiu més gran representable
L’exponent vàlid més gran en format normalitzat és \(e = +127\) (correspon a \(E_u = 254\); \(E_u = 255\) és reservat per a infinit i NaN). La fracció més gran possible és tota la fracció a 1:
\[F = 1111\,1111\,1111\,1111\,1111\,111_2 = 1 - 2^{-23}\]
Mantissa completa (amb bit ocult): \(1{,}1111\ldots1_2 = 2 - 2^{-23}\).
\[v_{max} = (2 - 2^{-23}) \times 2^{127} = 2^{128} - 2^{104}\]
\[\boxed{v_{max} = (2 - 2^{-23}) \times 2^{127} \approx 3{,}403 \times 10^{38} = \texttt{0x7F7FFFFF}}\]
b) Nombre positiu no nul més petit en format normalitzat
L’exponent vàlid normalitzat més petit és \(e = -126\) (\(E_u = 1\)). La mantissa normalitzada més petita és \(1{,}000\ldots0\) (fracció a zero, bit ocult = 1):
\[\boxed{v_{\min,\text{norm}} = 1{,}0 \times 2^{-126} \approx 1{,}175 \times 10^{-38} = \texttt{0x00800000}}\]
c) Nombre positiu no nul més petit en format subnormal
En format subnormal (\(E_u = 0\)), el valor és \(0{,}F \times 2^{-126}\). El valor no nul més petit s’obté amb un sol bit a 1 a la posició menys significativa de la fracció (1 ULP):
\[\boxed{v_{\min,\text{denorm}} = 2^{-23} \times 2^{-126} = 2^{-149} \approx 1{,}401 \times 10^{-45} = \texttt{0x00000001}}\]
Enunciat: Problema 14.5.
Els apartats a), c), d) i e) tenen part fraccionària que és suma finita de potències negatives de 2 (\(0\); \(0{,}125 = 2^{-3}\); \(0{,}75 = 2^{-1} + 2^{-2}\); \(0{,}5 = 2^{-1}\)): la conversió és exacta i no cal arrodonir. L’apartat b) té part fraccionària periòdica en binari i requereix arrodoniment.
a) 340 (exacte):
a) 340
c) −255,125 (exacte):
c) −255,125
d) −10,75 (exacte):
d) −10,75
e) 6,5 (exacte):
e) 6,5
b) 44,4 (amb arrodoniment):
Pas 1. Conversió a binari. Part entera: \(44 = 10\,1100_2\). Part fraccionària, per multiplicacions successives per 2: \(0{,}4 \to 0{,}8 \to 1{,}6 \to 1{,}2 \to 0{,}4 \to \ldots\), que dona l’expansió periòdica:
\[0{,}4 = 0{,}0110\,0110\,0110\ldots_2\]
Pas 2. Normalitzar:
\[44{,}4 = 10\,1100{,}0110\,0110\,0110\ldots_2 = 1{,}0110\,0011\,0011\,0011\,0011\,001\,\underbrace{1}_{G}\,\underbrace{0}_{R}\,\underbrace{0110\ldots}_{S}\ \times\ 2^5\]
Pas 3. Arrodonir (RNE). Els bits descartats són \(G = 1\), \(R = 0\) i \(S = 1\) (la cua periòdica conté uns): com que \(G = 1\) i \((R \lor S) = 1\), s’arrodoneix al següent (+1 al bit de menys pes):
Arrodoniment de la fracció (23 bits)
Pas 4. Codificar: \(e = 5 \Rightarrow E_u = 132 = 1000\,0100_2\):
\[V = 0\ |\ 1000\,0100\ |\ 011\,0001\,1001\,1001\,1001\,1010 = \texttt{0x4231999A}\]
Pas 5. Error de representació. Desfent la normalització de la mantissa arrodonida (coma 5 posicions a la dreta), la part entera (\(44\)) no ha canviat: l’error és la diferència entre les parts fraccionàries. La part fraccionària emmagatzemada val:
\[0{,}0110\,0110\,0110\,0110\,10_2 = 1\,1001\,1001\,1001\,1010_2 \times 2^{-18} = \frac{104\,858}{262\,144} = \frac{52\,429}{131\,072}\]
\[\varepsilon = \left|\frac{52\,429}{131\,072} - 0{,}4\right| = \frac{52\,429 - 0{,}4 \times 131\,072}{131\,072} = \frac{0{,}2}{131\,072} \approx 1{,}526 \times 10^{-6}\]
Resum:
| Apartat | Valor | IEEE 754 | Error |
|---|---|---|---|
| a) | \(340\) | 0x43AA0000 |
exacte |
| b) | \(44{,}4\) | 0x4231999A |
\(\approx 1{,}526 \times 10^{-6}\) |
| c) | \(-255{,}125\) | 0xC37F2000 |
exacte |
| d) | \(-10{,}75\) | 0xC12C0000 |
exacte |
| e) | \(6{,}5\) | 0x40D00000 |
exacte |
Enunciat: Problema 14.6.
Es treballa amb \(A = -1609{,}5\) i \(B = -938{,}8125\).
\(A = -1609{,}5\)
Part entera:
\[1609 = 1024 + 512 + 64 + 8 + 1 = 2^{10} + 2^9 + 2^6 + 2^3 + 2^0 = 11001001001_2\]
Part fraccionària:
\[0{,}5 = 0{,}1_2\]
\[A = -11001001001{,}1_2 = -1{,}10010010011_2 \times 2^{10}\]
La representació binària és exacta (la part fraccionària és \(0{,}5 = 2^{-1}\), representable en 1 bit).
Precisió simple (23 bits de fracció):
Els 11 bits de la fracció caben àmpliament als 23 bits disponibles: no hi ha arrodoniment.
Càlcul
\[\boxed{A_{\text{simple}} = \texttt{0xC4C93000}, \quad \varepsilon_A = 0}\]
Precisió doble (52 bits de fracció):
Igualment, sense arrodoniment (els 11 bits caben en 52).
Càlcul
\[\boxed{A_{\text{doble}} = \texttt{0xC099260000000000}, \quad \varepsilon_A = 0}\]
\(B = -938{,}8125\)
Part entera:
\[938 = 512 + 256 + 128 + 32 + 8 + 2 = 2^9 + 2^8 + 2^7 + 2^5 + 2^3 + 2^1 = 1110101010_2\]
Part fraccionària:
\[0{,}8125 = 0{,}5 + 0{,}25 + 0{,}0625 = 2^{-1} + 2^{-2} + 2^{-4} = 0{,}1101_2\]
\[B = -1110101010{,}1101_2 = -1{,}1101010101101_2 \times 2^9\]
La representació binària és exacta (la part fraccionària és \(0{,}8125\), representable en 4 bits).
Precisió simple:
La fracció té 13 bits (sense el bit ocult), que caben en els 23 bits disponibles: sense arrodoniment.
Càlcul
\[\boxed{B_{\text{simple}} = \texttt{0xC46AB400}, \quad \varepsilon_B = 0}\]
Precisió doble:
Igualment, sense arrodoniment.
Càlcul
\[\boxed{B_{\text{doble}} = \texttt{0xC08D568000000000}, \quad \varepsilon_B = 0}\]
Atenció: en aquest problema, tant \(A\) com \(B\) resulten ser exactament representables en precisió simple i doble: les seves parts fraccionàries (\(0{,}5\) i \(0{,}8125\)) són sumes de potències negatives de 2 amb un nombre finit de termes. En general, però, la majoria de decimals (per exemple, \(0{,}1\) o \(0{,}3\)) no són representables exactament en cap format binari de precisió finita i introdueixen sempre un error de representació.
23.2 Operacions
Enunciat: Problema 14.9.
Descodificació dels operands
ft2 = 0x417AC000
ft4 = 0x3F140000
Pas 1. Alinear exponents
L’exponent més petit és \(e = -1\) (ft4). Cal desplaçar la seva mantissa 4 posicions a la dreta per igualar \(e = 3\):
Alineació
Pas 2. Suma de mantisses
Suma
Pas 3. Renormalitzar
El resultat té un 1 extra a l’esquerra de la coma. Es desplaça 1 posició a la dreta i s’incrementa l’exponent:
Renormalització
Pas 4. Codificar el resultat
\[e = 4 \Rightarrow E_u = 4 + 127 = 131 = 1000\,0011_2\]
\[F = 000\,0010\,0000\,0000\,0000\,0000\]
\[\texttt{ft6} = 0\ |\ 1000\,0011\ |\ 000\,0010\,0000\,0000\,0000\,0000 = \texttt{0x41820000}\]
a) \(\boxed{\texttt{ft6} = \texttt{0x41820000}}\)
b) G = 0, R = 0, S = 0 → no cal arrodonir. No hi ha error de precisió.
c) \(e = 4\), mantissa \(= 1{,}0000010_2 = 1 + 2^{-6} = 1{,}015625\):
\[\texttt{ft6} = 1{,}015625 \times 2^4 = \mathbf{16{,}25}\]
Comprovació: \(15{,}671875 + 0{,}578125 = 16{,}25\) ✓
Enunciat: Problema 14.12.
Format half (Problema 14.7): 1 bit de signe, 5 bits d’exponent esbiaixat (biaix 15), 10 bits de fracció (amb bit ocult). El sumador manté els bits \(G\), \(R\) i \(S\) (Secció 5.1.7.1) i arrodoneix amb RNE.
a) A = 0xE4FE, B = 0xB640
Descodificació
A = 0xE4FE = 1 11001 0011111110
B = 0xB640 = 1 01101 1001000000
Pas 1. Alinear exponents
La diferència d’exponents és \(10 - (-2) = 12\): la mantissa de \(B\) es desplaça 12 posicions a la dreta. Els seus bits cauen tots fora dels 10 bits de fracció:
Alineació (Δe = 12)
El bit ocult de \(B\) arriba a la posició \(2^{-12}\) (\(R\)); per tant, \(G = 0\), \(R = 1\) i \(S = 1\) (els bits 1001 restants contenen uns).
Pas 2. Sumar les mantisses
Els dos operands són negatius (mateix signe): se sumen les magnituds. Dins dels 10 bits de fracció, \(B\) només aporta zeros, així que la mantissa no canvia:
Pas 3. Arrodonir (RNE)
\(G = 0\) → es trunca. Cal notar que \(R = S = 1\) no basta per arrodonir cap amunt: si \(G = 0\), el residu descartat és inferior a ½ ULP i la decisió és sempre truncar (Secció 5.1.7.1).
\[\boxed{A + B = -1278 = \texttt{0xE4FE} \;(= A)}\]
Precisió: \(B\) queda absorbit completament pel resultat. L’error absolut és \(|B| = 0{,}390625\), per sota de ½ ULP (l’ULP a \(e = 10\) val \(2^{-10} \times 2^{10} = 1\)): la fita d’error d’RNE es compleix.
b) A = 0x4DC7, B = 0x391D
Descodificació
A = 0x4DC7 = 0 10011 0111000111
B = 0x391D = 0 01110 0100011101
Pas 1. Alinear exponents
Diferència d’exponents: \(4 - (-1) = 5\); la mantissa de \(B\) es desplaça 5 posicions a la dreta:
Alineació (Δe = 5)
Per a \(B\) alineat: \(G = 1\), \(R = 1\) i \(S = 1\) (els bits 101 que queden més enllà contenen uns).
Pas 2. Sumar les mantisses
Suma
Pas 3. Arrodonir (RNE)
\(G = 1\) i \(R = 1\) → s’arrodoneix al següent (+1 al bit de menys pes):
Pas 4. Codificar el resultat
\[e = 4 \Rightarrow E_u = 19 = 10011_2 \qquad F = 01\,1111\,0000_2\]
\[0\ |\ 10011\ |\ 0111110000 = \texttt{0x4DF0}\]
\[\boxed{A + B = \texttt{0x4DF0} = 1\,0111{,}11_2 = 23{,}75}\]
Precisió: la suma exacta és \(23{,}109375 + 0{,}63916015625 = 23{,}74853515625\); l’error d’arrodoniment és
\[\varepsilon = 23{,}75 - 23{,}74853515625 = 0{,}00146484375\]
inferior a ½ ULP (\(= 2^{-11} \times 2^4 = 2^{-7} = 0{,}0078125\)).
Enunciat: Problema 14.13.
Se segueix l’algorisme de multiplicació (Secció 5.2.2): sumar exponents, calcular el signe (\(S_A \oplus S_B\)), multiplicar les mantisses (11 bits × 11 bits → fins a 22 bits), normalitzar comprovant el desbordament, arrodonir amb RNE i codificar.
a) A = 0x45A9, B = 0x484C
Descodificació
A = 0x45A9 = 0 10001 0110101001
B = 0x484C = 0 10010 0001001100
Pas 1. Exponent i signe: \(e = 2 + 3 = 5\); signe \(= 0 \oplus 0 = 0\) (positiu).
Pas 2. Multiplicar les mantisses
Producte de mantisses
Pas 3. Normalitzar: el producte ja és a \([1, 2)\): no cal renormalitzar; \(e = 5\).
Pas 4. Arrodonir (RNE): es conserven 10 bits de fracció; els descartats són \(G = 1\), \(R = 0\) i \(S = 1\) (0010 1100 conté uns) → s’arrodoneix al següent:
Pas 5. Codificar
\[e = 5 \Rightarrow E_u = 20 = 10100_2\]
\[0\ |\ 10100\ |\ 1000010101 = \texttt{0x5215}\]
\[\boxed{A \times B = \texttt{0x5215} = 11\,0000{,}10101_2 = 48{,}65625}\]
Precisió: el producte exacte és \(5{,}66015625 \times 8{,}59375 = 48{,}6419677734375\); l’error d’arrodoniment és
\[\varepsilon = 48{,}65625 - 48{,}6419677734375 = 0{,}0142822265625\]
inferior a ½ ULP (\(= 2^{-11} \times 2^5 = 2^{-6} = 0{,}015625\)).
b) A = 0x60D4, B = 0x533E
Descodificació
A = 0x60D4 = 0 11000 0011010100
B = 0x533E = 0 10100 1100111110
Pas 1. Exponent i signe: \(e = 9 + 5 = 14\); signe positiu.
Pas 2. Multiplicar les mantisses
Producte de mantisses
Pas 3. Normalitzar: es desplaça 1 posició a la dreta i s’incrementa l’exponent: \(e = 14 + 1 = 15\). Comprovació de desbordament: \(e = 15\) és exactament l’exponent màxim del format (\(E_u = 30\); \(E_u = 31\) està reservat per a \(\pm\infty\) i NaN): el resultat queda just al límit, sense desbordament.
Pas 4. Arrodonir (RNE): \(G = 1\), \(R = 1\) (\(S = 1\)) → s’arrodoneix al següent:
Pas 5. Codificar
\[e = 15 \Rightarrow E_u = 30 = 11110_2\]
\[0\ |\ 11110\ |\ 0001011111 = \texttt{0x785F}\]
\[\boxed{A \times B = \texttt{0x785F} = 100\,0101\,1111_2 \times 2^5 = 1119 \times 2^5 = 35\,808}\]
Precisió: el producte exacte és \(618 \times 57{,}9375 = 35\,805{,}375\); l’error d’arrodoniment és
\[\varepsilon = 35\,808 - 35\,805{,}375 = 2{,}625\]
Sembla un error gran, però és inferior a ½ ULP (\(= 2^{-11} \times 2^{15} = 2^4 = 16\)): en coma flotant l’ULP —i, per tant, l’error absolut— creix amb l’exponent; el que està acotat és l’error relatiu (aquí \(2{,}625 / 35\,805{,}375 \approx 7{,}3 \times 10^{-5}\)).
float
Enunciat: Problema 14.15.
En RV32F no hi ha operands immediats flotants: cap instrucció admet una constant de coma flotant directament. Per usar un literal cal declarar-lo al segment .data i llegir-lo de memòria amb la + flw.
a) f = 3.14;
RV32IF
b) f = g;
Per copiar entre registres de coma flotant s’usa la pseudoinstrucció fmv.s.
c) f = g + 3.14;
Cal llegir primer la constant de memòria i després fer la suma.
RV32IF
Atenció: la directiva .float accepta decimals: .float 3.14 converteix el valor a IEEE 754 de precisió simple en temps d’assemblatge. Però les instruccions de la família RV32F mai admeten literals numèrics flotants: tots els operands han d’estar en registres de coma flotant.
variancia amb crides a subrutina
Enunciat: Problema 14.17.
a) Anàlisi de les variables locals
variancia és una subrutina no fulla (non-leaf): crida a mitjana dues vegades.
| Variable | Tipus | Viu a través d’alguna crida? | Decisió |
|---|---|---|---|
vec (paràmetre) |
float * |
Sí: es fa servir al bucle (abans de la 1a crida) i a la 2a crida (m = mitjana(vec)) |
registre segur (cal preservar-lo) |
vquadrats[100] |
vector local (400 bytes) | Sí, però massa gran per a registres | al BA |
i |
int |
No: només viu dins el bucle, s’esgota abans de la 1a crida | registre temporal |
q |
float |
Sí: s’assigna a la 1a crida i es fa servir després de la 2a (return q - m*m) |
registre segur |
m |
float |
No: s’assigna després de la 2a crida i es fa servir tot seguit | registre temporal |
Només vec i q han de sobreviure a alguna crida i, per tant, necessiten un registre segur (s/fs) o el BA; i i m es podrien allotjar en registres temporals sense cap risc. Per uniformitat i simplicitat del codi es trien igualment tots quatre en registres segurs:
vec→s0(enter, preservat — necessari: sobreviu a una crida)q→fs1(flotant, preservat — necessari: sobreviu a una crida)i→s1(enter, preservat — no era imprescindible; un temporalthauria bastat)m→fs0(flotant, preservat — no era imprescindible; un temporalfthauria bastat)vquadrats→ BA (400 bytes)
Registres a preservar a la pila: ra (adreça de retorn), s0, s1, fs0, fs1. Abans de cada crida no cal desar cap registre temporal: tots els valors que la travessen són en registres segurs.
b) Traducció a RISC-V
Bloc d’activació de 420 bytes (Figura 23.1), múltiple de 4:
variancia: el vector vquadrats al desplaçament +0 i els registres desats fs1, fs0, s1, s0 i ra als desplaçaments +400, +404, +408, +412 i +416.
RV32IF
variancia:
# Pròleg
addi sp, sp, -420
sw ra, 416(sp)
sw s0, 412(sp)
sw s1, 408(sp)
fsw fs0, 404(sp)
fsw fs1, 400(sp)
mv s0, a0 # s0 ← vec (preserva l'argument)
# Bucle: vquadrats[i] = vec[i] * vec[i] per a i = 0..99
li s1, 0 # i = 0
bucle:
li t0, 100
bge s1, t0, fibucle
slli t1, s1, 2 # t1 ← i * 4
add t2, s0, t1 # t2 ← &vec[i]
flw fa0, 0(t2) # fa0 ← vec[i]
fmul.s ft0, fa0, fa0 # ft0 ← vec[i] * vec[i]
addi t3, sp, 0 # t3 ← &vquadrats[0]
add t3, t3, t1 # t3 ← &vquadrats[i]
fsw ft0, 0(t3) # vquadrats[i] ← vec[i] * vec[i]
addi s1, s1, 1 # i++
j bucle
fibucle:
# q = mitjana(vquadrats)
mv a0, sp # a0 ← &vquadrats[0]
call mitjana
fmv.s fs1, fa0 # fs1 ← q
# m = mitjana(vec)
mv a0, s0 # a0 ← vec
call mitjana
fmv.s fs0, fa0 # fs0 ← m
# return q - m * m
fmul.s ft0, fs0, fs0 # ft0 ← m * m
fsub.s fa0, fs1, ft0 # fa0 ← q - m * m
# Epíleg
flw fs1, 400(sp)
flw fs0, 404(sp)
lw s1, 408(sp)
lw s0, 412(sp)
lw ra, 416(sp)
addi sp, sp, 420
retfloat en memòria
Enunciat: Problema 14.19.
a) Lectura de v[0] i v[2]
Cada element float ocupa 4 bytes. v[2] és a un desplaçament de \(2 \times 4 = 8\) bytes respecte de la base.
b) Suma i escriptura a resultat
RV32IF
c) Comparació v[0] > v[2] amb flt.s
flt.s calcula \(rd = (rs1 < rs2)\ ?\ 1 : 0\). Per obtenir \(v[0] > v[2]\) cal invertir els operands: \(v[0] > v[2] \Leftrightarrow v[2] < v[0]\).
Cal recarregar fa0 i fa1 perquè l’apartat b) ha sobreescrit fa0:
RV32IF
Per a v[0] = 1.5 i v[2] = 3.25, \(1{,}5 \not> 3{,}25\), per tant, t0 = 0.
Atenció: flt.s rd, rs1, rs2 avalua \(rs1 < rs2\), no \(rs1 > rs2\). Per implementar a > b, cal escriure flt.s rd, b, a (invertir l’ordre dels operands), no negar el resultat amb xori.
int i float
Enunciat: Problema 14.20.
a) int i = (int) f;
La conversió de tipus (int) de C trunca cap a zero: cal indicar-ho explícitament amb el mode rtz.
b) float f = (float) i;
c) unsigned int u = (unsigned int) f;
d) Càlcul manual per a f = 3.9
fcvt.w.s/fcvt.wu.s s’arrodoneixen segons el mode indicat: no trunquen per si mateixes. Sense operand de mode, l’assemblador hi assigna dyn (el mode vigent al frm, RNE per defecte). Per traduir la conversió (int) de C —que trunca sempre cap a zero— cal l’operand explícit rtz, com a l’apartat a).
\(3{,}9\) en IEEE 754 de precisió simple no és exactament representable. El valor emmagatzemat és:
\[3{,}9 \approx 1{,}1111001100110011001101_2 \times 2^1 = 3{,}9000000953\ldots\]
Aplicant fcvt.w.s a0, fa0, rtz (truncament cap a zero, com la conversió (int) de C):
\[\lfloor 3{,}9000\ldots \rfloor = 3\]
Resultat: a0 = 3.
Es tracta d’un truncament, no d’un arrodoniment: el valor emmagatzemat (\(3{,}9000000953\ldots\)) ja és lleugerament superior a \(3{,}9\); amb rtz la part fraccionària es descarta directament. Si s’hagués escrit fcvt.w.s a0, fa0 sense mode (dyn → RNE per defecte), el resultat seria a0 = 4 (arrodoniment al més pròxim), no 3.
23.3 No-associativitat
Enunciat: Problema 14.21.
a) A = 0xF3FD, B = 0x73FD, C = 0x3C00 en format half (1 bit signe, 5 bits exponent esbiaixat (biaix 15), 10 bits fracció).
Descodificació
A = 0xF3FD = 1 11100 1111111101
B = 0x73FD = 0 11100 1111111101
C = 0x3C00 = 0 01111 0000000000
Càlcul de \((A + B) + C\)
Pas 1: \(A + B\)
\(A\) i \(B\) tenen el mateix exponent i la mateixa fracció però signes oposats: \(A = -B\) exactament. La suma és zero sense cap error d’arrodoniment:
\[A + B = 0 \quad (\texttt{0x0000})\]
Pas 2: \(0 + C\)
\[0 + 1 = 1 \quad (\texttt{0x3C00})\]
\[\boxed{(A + B) + C = 1}\]
Càlcul de \(A + (B + C)\)
Pas 1: \(B + C\)
\(e_B = 13\), \(e_C = 0\), diferència = 13. Cal desplaçar la mantissa de \(C\) 13 posicions a la dreta per alinear-la amb \(B\):
Alineació de C amb B
Els 10 bits de fracció de \(B\) cobreixen les posicions \(2^{-1}\) fins a \(2^{-10}\). El bit ocult de \(C\) desplaçat arriba a la posició \(2^{-13}\), tres posicions més enllà del darrer bit de fracció. Per tant:
- \(G = 0\) (posició \(2^{-11}\): cap bit de \(C\) arriba aquí).
- \(R = 0\) (posició \(2^{-12}\): ídem).
- \(S = 1\) (posicions \(\leq 2^{-13}\): hi ha el bit ocult de \(C\)).
Com que \(G = 0\), la regla RNE no arrodoneix cap amunt. \(C\) es perd completament:
\[B + C = B = +16360 \quad (\texttt{0x73FD})\]
Pas 2: \(A + (B + C)\)
\[A + 16360 = -16360 + 16360 = 0 \quad (\texttt{0x0000})\]
\[\boxed{A + (B + C) = 0}\]
Conclusió
\[(A + B) + C = 1 \neq 0 = A + (B + C)\]
La suma en coma flotant no és associativa. La pèrdua de precisió es produeix en calcular \(B + C\): els exponents de \(C = 1\) i de \(B = 16360\) difereixen en 13, més que els 10 bits de fracció del format half, i \(C\) queda completament absorbit per l’arrodoniment. En canvi, quan es calcula \((A+B)\) primer, la cancel·lació exacta de \(A\) i \(B\) deixa zero, i llavors \(C\) és prou gran per ser representat.
b) A = 0x4F2A, B = 0x36A0, C = 0x4A12.
Descodificació
Càlcul de \((A + B) + C\)
Pas 1: \(A + B\). Els exponents difereixen en 6: la mantissa de \(B\) es desplaça 6 posicions a la dreta. El bit que cau a la posició \(2^{-11}\) és un 1 (\(G\)), i tots els de després, zeros (\(R = S = 0\)):
A + B
\(G R S = 100\) és un empat: RNE arrodoneix al parell, i el bit de menys pes ja és 0. El resultat, \(1{,}1101000100_2 imes 2^4 = 29{,}0625\) (0x4F44), ha perdut el \(2^{-7}\) de \(B\) (la suma exacta és \(29{,}0703125\)).
Pas 2: \((A + B) + C\). Diferència d’exponents 1:
(A + B) + C
En normalitzar, el bit de menys pes surt cap a \(G\): torna a ser un empat, i el bit de menys pes és 0.
\[\boxed{(A + B) + C = 1{,}0100100110_2 \times 2^5 = 41{,}1875 \quad (\texttt{0x5126})}\]
Càlcul de \(A + (B + C)\)
Pas 1: \(B + C\). Diferència d’exponents 5: els cinc primers bits de la fracció de \(B\) queden dins dels 10 de \(C\), i la resta són zeros. La suma és exacta:
B + C
Pas 2: \(A + (B + C)\). Diferència d’exponents 1:
A + (B + C)
En normalitzar, el bit de menys pes passa a \(G\) i l’antic \(G\), a \(R\): \(G R S = 110\), més de la meitat, i RNE arrodoneix cap amunt.
\[\boxed{A + (B + C) = 1{,}0100100111_2 \times 2^5 = 41{,}21875 \quad (\texttt{0x5127})}\]
Conclusió
\[(A + B) + C = 41{,}1875 \neq 41{,}21875 = A + (B + C)\]
Els dos resultats difereixen en una unitat de l’última posició (\(2^{5-10} = 0{,}03125\)). La suma exacta és \(41{,}2109375\): \(A + (B + C)\) n’és més a prop, perquè \(B + C\) és exacta, mentre que \(A + B\) perd els bits de menys pes de \(B\) en un empat arrodonit cap avall.
Enunciat: Problema 14.22.
Els operands són els mateixos que les conversions de Problema 14.8 (apartats b i c). Cada operació s’arrodoneix amb RNE abans de la següent.
a) A = 0x30E0, B = 0x32A0, C = 0x563B
Descodificació
A = 0x30E0 = 0 01100 0011100000
B = 0x32A0 = 0 01100 1010100000
C = 0x563B = 0 10101 1000111011
Operació 1: \(B + C\) (per al camí de l’esquerra)
Diferència d’exponents: \(6 - (-3) = 9\); la mantissa de \(B\) es desplaça 9 posicions a la dreta:
Alineació (Δe = 9)
\(G = 0\) → es trunca:
\[B + C = 0\ |\ 10101\ |\ 1000111110 = \texttt{0x563E} = 110\,0011{,}1110_2 = 99{,}875\]
(La suma exacta és \(99{,}89453125\): error \(0{,}01953125 < \tfrac{1}{2}\,\text{ULP} = 2^{-5}\).)
Operació 2: \(A \times (B + C)\)
Exponent: \(e = -3 + 6 = 3\); signe positiu. Producte de mantisses:
Producte de mantisses
\(G = 1\), \(R = 0\), \(S = 1\) → al següent: \(F = 1110011011 + 1 = 1110011100\):
\[A \times (B + C) = 0\ |\ 10010\ |\ 1110011100 = \texttt{0x4B9C} = 1111{,}00111_2 = \mathbf{15{,}21875}\]
Operació 3: \(A \times B\) (per al camí de la dreta)
Exponent: \(e = -3 + (-3) = -6\); signe positiu. Producte de mantisses:
Producte de mantisses
Els bits descartats són \(G = 1\), \(R = 0\) i \(S = 0\): el residu val exactament ½ ULP → empat. La regla del parell decideix: la fracció truncada 0000001001 acaba en 1 (senar), així que s’arrodoneix amunt perquè el resultat acabi en bit parell:
\[F = 0000001001 + 1 = 0000001010\]
\[A \times B = 0\ |\ 01010\ |\ 0000001010 = \texttt{0x280A} = 0{,}03155517578125\]
(És l’únic problema resolt de T5 on el desempat «al parell» entra en joc: l’error comès és exactament ½ ULP \(= 2^{-16}\).)
Operació 4: \(A \times C\)
Exponent: \(e = -3 + 6 = 3\); signe positiu. Producte de mantisses:
Producte de mantisses
\(G = 1\), \(R = 1\) → al següent: \(F = 1110010111 + 1 = 1110011000\):
\[A \times C = 0\ |\ 10010\ |\ 1110011000 = \texttt{0x4B98} = 1111{,}0011_2 = 15{,}1875\]
Operació 5: \((A \times B) + (A \times C)\)
Diferència d’exponents: \(3 - (-5) = 8\); la mantissa de \(A \times B\) es desplaça 8 posicions:
Alineació (Δe = 8)
\(G = 0\) → es trunca:
\[(A \times B) + (A \times C) = 0\ |\ 10010\ |\ 1110011100 = \texttt{0x4B9C} = \mathbf{15{,}21875}\]
Comparació de l’apartat a)
\[\boxed{A \times (B + C) = \texttt{0x4B9C} = 15{,}21875 = (A \times B) + (A \times C)}\]
En aquest cas els dos camins coincideixen, tot i haver acumulat cinc arrodoniments (dos truncaments, dos «al següent» i un empat «al parell»). Els resultats exactes de l’última operació de cada camí, calculats amb els intermedis ja arrodonits, són diferents (\(15{,}21533\ldots\) i \(15{,}21905\ldots\)), i el valor exacte d’\(A \times (B + C)\) és \(15{,}2183\ldots\): tots dos s’arrodoneixen casualment al mateix representable. La igualtat és fortuïta, no una propietat.
b) A = 0xCEF9, B = 0xEFE6, C = 0x70FD
Descodificació
A = 0xCEF9 = 1 10011 1011111001
B = 0xEFE6 = 1 11011 1111100110
C = 0x70FD = 0 11100 0011111101
Operació 1: \(B + C\)
Els signes són diferents: es resten les magnituds i el resultat pren el signe de l’operand més gran (\(C\), positiu). Diferència d’exponents: \(13 - 12 = 1\):
Alineació i resta (Δe = 1)
El resultat es renormalitza desplaçant 2 posicions a l’esquerra (\(e = 13 - 2 = 11\)):
\[B + C = 0\ |\ 11010\ |\ 0000101000 = \texttt{0x6828} = 1000\,0101\,0000_2 = 2128 \quad \text{(exacte)}\]
Operació 2: \(A \times (B + C)\)
Exponent: \(e = 4 + 11 = 15\), just el màxim del format: si el producte de mantisses arribés a 2, la renormalització provocaria desbordament. Signe: \((-) \cdot (+) = -\).
Producte de mantisses
\(G = 1\), \(R = 0\), \(S = 1\) → al següent: \(F = 1100111110 + 1 = 1100111111\):
\[A \times (B + C) = 1\ |\ 11110\ |\ 1100111111 = \texttt{0xFB3F} = -1855 \times 2^5 = \mathbf{-59\,360}\]
(El producte exacte és \(-59\,351{,}25\): error \(8{,}75 < \tfrac{1}{2}\,\text{ULP} = 2^4 = 16\).)
Operacions 3 i 4: \(A \times B\) i \(A \times C\) — desbordament
Per a \(A \times B\), la suma d’exponents ja és \(e = 4 + 12 = 16 > e_{max} = 15\). Com que el producte de dues mantisses normalitzades és sempre \(\geq 1\), la normalització mai no redueix l’exponent per sota d’aquesta suma: el resultat supera amb seguretat el màxim representable del format half, \((2 - 2^{-10}) \times 2^{15} = 65\,504\), sense necessitat de multiplicar les mantisses. Desbordament: amb RNE el resultat es converteix en infinit, amb el signe del producte:
\[A \times B \to (-)(-) = +\infty = \texttt{0x7C00} \qquad (|A \times B| \approx 2{,}3 \times 10^5)\]
\[A \times C:\ e = 4 + 13 = 17 > 15 \to (-)(+) = -\infty = \texttt{0xFC00} \qquad (|A \times C| \approx 2{,}8 \times 10^5)\]
Operació 5: \((A \times B) + (A \times C)\)
\[(+\infty) + (-\infty) = \infty - \infty \to \textbf{NaN}\]
L’operació no té cap valor definit (Secció 5.1.6.4): el resultat és un NaN silenciós, amb \(E_u = 31\) i el bit de més pes de la fracció a 1 (per exemple, 0x7E00; l’estàndard no en fixa la resta de la fracció).
Comparació de l’apartat b)
\[\boxed{A \times (B + C) = -59\,360 \;(\texttt{0xFB3F}) \neq \text{NaN} = (A \times B) + (A \times C)}\]
Conclusió
La multiplicació no és distributiva sobre la suma en coma flotant. L’apartat a) mostra que la igualtat es pot donar fortuïtament; l’apartat b) mostra la fallada extrema: factoritzar l’expressió (calcular primer \(B + C = 2128\)) manté tots els resultats intermedis representables, mentre que expandir-la fa desbordar els dos productes parcials cap a \(\pm\infty\) i el resultat final és NaN. Com en la no-associativitat (Essencial 5.6), l’ordre de les operacions altera el resultat: reordenar algebraicament un càlcul en coma flotant no és mai «gratuït».