Tema 5: Coma flotant

23.1 Representació IEEE 754

Exemple 23.1: Solució: interpretació de patrons de bits

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
0 | 1000 0000 | 111 0011 0000 0010 1011 0011
S = 0  (positiu)
Eu = 1000 0000b = 128  →  e = 128 - 127 = 1
F  = 111 0011 0000 0010 1011 0011
Valor    = 1,111 0011 0000 0010 1011 0011 × 2¹
Càlcul B = 0xF9C40513
1 | 1111 0011 | 100 0100 0000 0101 0001 0011
S = 1  (negatiu)
Eu = 1111 0011b = 243  →  e = 243 - 127 = 116
F  = 100 0100 0000 0101 0001 0011
Valor    = 1,100 0100 0000 0101 0001 0011 × 2¹¹⁶

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
opcode = 011 0011b = 0x33  →  OP (tipus R)
funct7 = 010 0000b = 0x20
funct3 = 000b
rd  = 00101b = x5  (t0)
rs1 = 00110b = x6  (t1)
rs2 = 00111b = x7  (t2)
funct7=0x20, funct3=0 → SUB

\[\boxed{A: \texttt{sub t0, t1, t2}}\]

Càlcul B = 0xF9C40513
opcode = 001 0011b = 0x13  →  OP-IMM (tipus I)
funct3 = 000b  →  ADDI
rd  = 01010b = x10  (a0)
rs1 = 01000b = x8   (s0)
imm = 1111 1001 1100b = -100  (extensió de signe: bit 11 = 1)

\[\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.

Exemple 23.2: Solució: classificació de patrons IEEE 754

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\).
Exemple 23.3: Solució: rang del format IEEE 754 de precisió simple

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}\]

Càlcul
S = 0
Eu = 1111 1110b = 254
F  = 111 1111 1111 1111 1111 1111b
→  0x7F7FFFFF

\[\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):

Càlcul
S = 0
Eu = 0000 0001b = 1
F  = 000 0000 0000 0000 0000 0000b
→  0x00800000

\[\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):

Càlcul
S = 0
Eu = 0000 0000b = 0
F  = 000 0000 0000 0000 0000 0001b
→  0x00000001

\[\boxed{v_{\min,\text{denorm}} = 2^{-23} \times 2^{-126} = 2^{-149} \approx 1{,}401 \times 10^{-45} = \texttt{0x00000001}}\]

Exemple 23.4: Solució: codificació de decimal a IEEE 754

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
340 = 1 0101 0100b = 1,01010100 × 2⁸
e = 8  →  Eu = 8 + 127 = 135 = 1000 0111b
F = 010 1010 0000 0000 0000 0000
0 | 1000 0111 | 010 1010 0000 0000 0000 0000  =  0x43AA0000

c) −255,125 (exacte):

c) −255,125
255 = 1111 1111b     0,125 = 0,001b
−255,125 = −1111 1111,001b = −1,1111111001 × 2⁷
e = 7  →  Eu = 134 = 1000 0110b
F = 111 1111 0010 0000 0000 0000
1 | 1000 0110 | 111 1111 0010 0000 0000 0000  =  0xC37F2000

d) −10,75 (exacte):

d) −10,75
10 = 1010b     0,75 = 0,11b
−10,75 = −1010,11b = −1,01011 × 2³
e = 3  →  Eu = 130 = 1000 0010b
F = 010 1100 0000 0000 0000 0000
1 | 1000 0010 | 010 1100 0000 0000 0000 0000  =  0xC12C0000

e) 6,5 (exacte):

e) 6,5
6 = 110b     0,5 = 0,1b
6,5 = 110,1b = 1,101 × 2²
e = 2  →  Eu = 129 = 1000 0001b
F = 101 0000 0000 0000 0000 0000
0 | 1000 0001 | 101 0000 0000 0000 0000 0000  =  0x40D00000

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)
F truncada   = 011 0001 1001 1001 1001 1001   (G=1, R=0, S=1)
F arrodonida = 011 0001 1001 1001 1001 1010

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
Exemple 23.5: Solució: precisió simple i doble, error de representació

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
S = 1
e = 10  →  Eu = 10 + 127 = 137 = 1000 1001b
F = 100 1001 0011 0000 0000 0000  (omplim amb zeros fins a 23 bits)
→  0xC4C93000

\[\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
S = 1
e = 10  →  Eu = 10 + 1023 = 1033 = 100 0000 1001b
F = 1001 0010 0110 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000  (zeros fins a 52 bits)
→  0xC099260000000000

\[\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
S = 1
e = 9  →  Eu = 9 + 127 = 136 = 1000 1000b
F = 110 1010 1011 0100 0000 0000  (zeros fins a 23 bits)
→  0xC46AB400

\[\boxed{B_{\text{simple}} = \texttt{0xC46AB400}, \quad \varepsilon_B = 0}\]

Precisió doble:

Igualment, sense arrodoniment.

Càlcul
S = 1
e = 9  →  Eu = 9 + 1023 = 1032 = 100 0000 1000b
F = 1101 0101 0110 1000 0000 ... (zeros fins a 52 bits)
→  0xC08D568000000000

\[\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

Exemple 23.6: Solució: suma de nombres en coma flotant

Enunciat: Problema 14.9.

Descodificació dels operands

ft2 = 0x417AC000
0 | 1000 0010 | 111 1010 1100 0000 0000 0000
S=0, Eu=130 → e = 130−127 = 3
Mantissa = 1,111 1010 1100 0000 0000 0000
Valor = 1,111 1010 1100b × 2³ = 15,671875
ft4 = 0x3F140000
0 | 0111 1110 | 001 0100 0000 0000 0000 0000
S=0, Eu=126 → e = 126−127 = −1
Mantissa = 1,001 0100 0000 0000 0000 0000
Valor = 1,001 0100 0000b × 2⁻¹ = 0,578125

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ó
ft2:            1,1111010110 0000000000000          × 2³
ft4 original:   1,0010100000 0000000000000          × 2⁻¹
ft4 alineat:    0,0001001010 0000000000000          × 2³
                (els 4 bits que surten per la dreta són 0: G=0, R=0, S=0)

Pas 2. Suma de mantisses

Suma
  1,1111010110 0000000000000
+ 0,0001001010 0000000000000
= 10,0000100000 0000000000000
  ↑
  ròssec = 1 → cal renormalitzar

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ó
10,0000100000 0000000000000 × 2³
→  1,0000010000 0000000000000 × 2⁴   (G=0, sense arrodoniment)

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\) ✓

Exemple 23.7: Solució: suma en format half amb bits de guarda

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
S=1, Eu=11001b=25 → e = 25−15 = 10
Mantissa = 1,0011111110
Valor = −1,0011111110b × 2¹⁰ = −100 1111 1110b = −1278
B = 0xB640 = 1 01101 1001000000
S=1, Eu=01101b=13 → e = 13−15 = −2
Mantissa = 1,1001000000
Valor = −1,1001b × 2⁻² = −0,011001b = −0,390625

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)
A:          1,0011111110                  × 2¹⁰
B original: 1,1001000000                  × 2⁻²
B alineat:  0,0000000000 | 0 1 | 1001…    × 2¹⁰
            ← 10 bits →    G R    S

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:

Suma
  1,0011111110 | 011…
= 1,0011111110   amb G=0, R=1, S=1     (sense transport: no cal renormalitzar)

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
S=0, Eu=10011b=19 → e = 19−15 = 4
Mantissa = 1,0111000111
Valor = 1,0111000111b × 2⁴ = 1 0111,000111b = 23,109375
B = 0x391D = 0 01110 0100011101
S=0, Eu=01110b=14 → e = 14−15 = −1
Mantissa = 1,0100011101
Valor = 1,0100011101b × 2⁻¹ = 0,10100011101b = 0,63916015625

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)
A:          1,0111000111                  × 2⁴
B original: 1,0100011101                  × 2⁻¹
B alineat:  0,0000101000 | 1 1 | 101      × 2⁴
            ← 10 bits →    G R    S

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
  1,0111000111 | 000
+ 0,0000101000 | 111
= 1,0111101111 | 111        (sense transport: no cal renormalitzar)

Pas 3. Arrodonir (RNE)

\(G = 1\) i \(R = 1\) → s’arrodoneix al següent (+1 al bit de menys pes):

Arrodoniment
  1,0111101111
+ 0,0000000001
= 1,0111110000

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\)).

Exemple 23.8: Solució: multiplicació en format half

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
S=0, Eu=10001b=17 → e = 17−15 = 2
Mantissa = 1,0110101001  (= 1449/1024)
Valor = 1,0110101001b × 2² = 101,10101001b = 5,66015625
B = 0x484C = 0 10010 0001001100
S=0, Eu=10010b=18 → e = 18−15 = 3
Mantissa = 1,0001001100  (= 1100/1024)
Valor = 1,00010011b × 2³ = 1000,10011b = 8,59375

Pas 1. Exponent i signe: \(e = 2 + 3 = 5\); signe \(= 0 \oplus 0 = 0\) (positiu).

Pas 2. Multiplicar les mantisses

Producte de mantisses
1449 × 1100 = 1 593 900
(1449/1024) × (1100/1024) = 1 593 900 / 2²⁰
1 593 900 = 1 1000 0101 0010 0010 1100b            (21 bits)
Producte  = 1,1000 0101 0010 0010 1100             (1 ≤ producte < 2)

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:

Arrodoniment
F truncada   = 1000010100   (G=1, R=0, S=1)
F arrodonida = 1000010101

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
S=0, Eu=11000b=24 → e = 24−15 = 9
Mantissa = 1,0011010100  (= 1236/1024)
Valor = 1,00110101b × 2⁹ = 10 0110 1010b = 618
B = 0x533E = 0 10100 1100111110
S=0, Eu=10100b=20 → e = 20−15 = 5
Mantissa = 1,1100111110  (= 1854/1024)
Valor = 1,1100111110b × 2⁵ = 11 1001,11110b = 57,9375

Pas 1. Exponent i signe: \(e = 9 + 5 = 14\); signe positiu.

Pas 2. Multiplicar les mantisses

Producte de mantisses
1236 × 1854 = 2 291 544
2 291 544 = 10 0010 1111 0111 0101 1000b           (22 bits)
Producte  = 10,0010 1111 0111 0101 1000            (≥ 2: cal renormalitzar)

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.

Producte normalitzat
1,0001 0111 1011 1010 1100 0   × 2¹⁵

Pas 4. Arrodonir (RNE): \(G = 1\), \(R = 1\) (\(S = 1\)) → s’arrodoneix al següent:

Arrodoniment
F truncada   = 0001011110   (G=1, R=1, S=1)
F arrodonida = 0001011111

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}\)).

Exemple 23.9: Solució: traducció de sentències amb 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
.data
const_pi:
        .float  3.14

.text
        la      t0, const_pi    # t0 ← @const_pi
        flw     fa2, 0(t0)      # fa2 ← 3.14  (f = 3.14)

b) f = g;

Per copiar entre registres de coma flotant s’usa la pseudoinstrucció fmv.s.

RV32IF
        fmv.s   fa2, fa4        # fa2 ← fa4  (f = g)

c) f = g + 3.14;

Cal llegir primer la constant de memòria i després fer la suma.

RV32IF
.data
const_pi:
        .float  3.14

.text
        la      t0, const_pi    # t0 ← @const_pi
        flw     ft0, 0(t0)      # ft0 ← 3.14
        fadd.s  fa2, fa4, ft0   # fa2 ← fa4 + 3.14  (f = g + 3.14)

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.

Exemple 23.10: Solució: funció 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 temporal t hauria bastat)
  • m → fs0 (flotant, preservat — no era imprescindible; un temporal ft hauria 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:

Bloc d'activació de 420 bytes, d'adreces baixes (sp) a altes: vquadrats (float[100], 400 bytes, desplaçament +0, amb el mig elidit) i els registres desats fs1 (+400), fs0 (+404), s1 (+408), s0 (+412) i ra (+416).

Bloc d'activació de 420 bytes, d'adreces baixes (sp) a altes: vquadrats (float[100], 400 bytes, desplaçament +0, amb el mig elidit) i els registres desats fs1 (+400), fs0 (+404), s1 (+408), s0 (+412) i ra (+416).

Figura 23.1: Bloc d’activació de 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
        ret
Exemple 23.11: Solució: lectura, suma i comparació de float en memòria

Enunciat: Problema 14.19.

C
float v[4] = {1.5, -2.0, 3.25, 0.5};
float resultat;

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.

RV32IF
        la      t0, v           # t0 ← @v
        flw     fa0, 0(t0)      # fa0 ← v[0] = 1.5
        flw     fa1, 8(t0)      # fa1 ← v[2] = 3.25

b) Suma i escriptura a resultat

RV32IF
        fadd.s  fa0, fa0, fa1   # fa0 ← v[0] + v[2] = 4.75
        la      t1, resultat
        fsw     fa0, 0(t1)      # resultat ← 4.75

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
        la      t0, v
        flw     fa0, 0(t0)      # fa0 ← v[0] = 1.5
        flw     fa1, 8(t0)      # fa1 ← v[2] = 3.25
        flt.s   t0, fa1, fa0    # t0 ← (v[2] < v[0]) ? 1 : 0
                                # = (3.25 < 1.5) ? 1 : 0 = 0

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.

Exemple 23.12: Solució: conversions entre 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.

RV32IF
        fcvt.w.s a0, fa0, rtz   # a0 ← (int) fa0  [rtz: trunca cap a zero, com el cast de C]

b) float f = (float) i;

RV32IF
        fcvt.s.w fa0, a0        # fa0 ← (float) a0

c) unsigned int u = (unsigned int) f;

RV32IF
        fcvt.wu.s a0, fa0, rtz  # a0 ← (unsigned int) fa0  [rtz: trunca cap a zero, com el cast de C]

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

Exemple 23.13: Solució: no-associativitat de la suma en coma flotant

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
S=1, Eu=11100b=28 → e = 28−15 = 13
F = 11 1111 1101b = 1021
mantissa = 1 + 1021/1024 = 2045/1024
Valor = −(2045/1024) × 2¹³ = −2045 × 2³ = −16360
B = 0x73FD = 0 11100 1111111101
S=0, Eu=28 → e=13  (mateixa fracció que A, signe oposat)
Valor = +16360
C = 0x3C00 = 0 01111 0000000000
S=0, Eu=01111b=15 → e = 15−15 = 0
F = 00 0000 0000b = 0
Valor = 1,0000000000 × 2⁰ = 1

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
B:          1,1111111101  × 2¹³   (10 bits de fracció)
C original: 1,0000000000  × 2⁰
C alineat:  0,0000000000001...  × 2¹³
              ← 10 bits→↑ posició −11 (Guard)

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ó
A = 0x4F2A = 0 10011 1100101010   e = 19−15 = 4    mantissa 1,1100101010   valor 28,65625
B = 0x36A0 = 0 01101 1010100000   e = 13−15 = −2   mantissa 1,1010100000   valor 0,4140625
C = 0x4A12 = 0 10010 1000010010   e = 18−15 = 3    mantissa 1,1000010010   valor 12,140625

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
A:          1,1100101010           × 2⁴
B alineat:  0,0000011010 | 1 0 0   × 2⁴   (G R S)
Suma:       1,1101000100 | 1 0 0   × 2⁴

\(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
A+B:         1,1101000100           × 2⁴
C alineat:   0,1100001001 | 0 0 0   × 2⁴
Suma:       10,1001001101 | 0 0 0   × 2⁴
Normalitzat: 1,0100100110 | 1 0 0   × 2⁵

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
C:          1,1000010010           × 2³
B alineat:  0,0000110101 | 0 0 0   × 2³
Suma:       1,1001000111 | 0 0 0   × 2³   = 12,5546875 (0x4A47)

Pas 2: \(A + (B + C)\). Diferència d’exponents 1:

A + (B + C)
A:           1,1100101010           × 2⁴
B+C alineat: 0,1100100011 | 1 0 0   × 2⁴
Suma:       10,1001001101 | 1 0 0   × 2⁴
Normalitzat: 1,0100100110 | 1 1 0   × 2⁵

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.

Exemple 23.14: Solució: no-distributivitat de la multiplicació sobre la suma

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
S=0, Eu=01100b=12 → e = 12−15 = −3
Mantissa = 1,0011100000  (= 1248/1024)
Valor = 1,00111b × 2⁻³ = 0,00100111b = 0,15234375
B = 0x32A0 = 0 01100 1010100000
S=0, Eu=12 → e = −3
Mantissa = 1,1010100000  (= 1696/1024)
Valor = 1,10101b × 2⁻³ = 0,00110101b = 0,20703125
C = 0x563B = 0 10101 1000111011
S=0, Eu=10101b=21 → e = 21−15 = 6
Mantissa = 1,1000111011  (= 1595/1024)
Valor = 1,1000111011b × 2⁶ = 110 0011,1011b = 99,6875

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)
C:          1,1000111011                  × 2⁶
B original: 1,1010100000                  × 2⁻³
B alineat:  0,0000000011 | 0 1 | 01…      × 2⁶
            ← 10 bits →    G R    S
Suma
  1,1000111011 | 000
+ 0,0000000011 | 011
= 1,1000111110 | 011        (sense ròssec)

\(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
1248 × 1598 = 1 994 304 = 1 1110 0110 1110 0100 0000b   (21 bits)
Producte = 1,1110 0110 1110 0100 0000                   (< 2: no cal renormalitzar)

\(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
1248 × 1696 = 2 116 608 = 10 0000 0100 1100 0000 0000b  (22 bits)
Producte = 10,0000 0100 1100 0000 0000                  (≥ 2: renormalitzar)
→ 1,0000 0100 1100 0000 0000 0  × 2⁻⁵

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
1248 × 1595 = 1 990 560 = 1 1110 0101 1111 1010 0000b   (21 bits)
Producte = 1,1110 0101 1111 1010 0000                   (< 2: no cal renormalitzar)

\(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)
A×C:          1,1110011000                    × 2³
A×B original: 1,0000001010                    × 2⁻⁵
A×B alineat:  0,0000000100 | 0 0 | 001010     × 2³
              ← 10 bits →    G R    S
Suma
  1,1110011000 | 000
+ 0,0000000100 | 001
= 1,1110011100 | 001        (sense transport)

\(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
S=1, Eu=10011b=19 → e = 19−15 = 4
Mantissa = 1,1011111001  (= 1785/1024)
Valor = −1,1011111001b × 2⁴ = −1 1011,111001b = −27,890625
B = 0xEFE6 = 1 11011 1111100110
S=1, Eu=11011b=27 → e = 27−15 = 12
Mantissa = 1,1111100110  (= 2022/1024)
Valor = −(2022/1024) × 2¹² = −2022 × 2² = −8088
C = 0x70FD = 0 11100 0011111101
S=0, Eu=11100b=28 → e = 28−15 = 13
Mantissa = 1,0011111101  (= 1277/1024)
Valor = (1277/1024) × 2¹³ = 1277 × 2³ = 10 216

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)
C:          1,0011111101 0        × 2¹³
B alineat:  0,1111110011 0        × 2¹³     (el desplaçament d'1 bit no en perd cap)
Resta:      0,0100001010 0                  (exacta: G=R=S=0)

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
1785 × 1064 = 1 899 240 = 1 1100 1111 1010 1110 1000b   (21 bits)
Producte = 1,1100 1111 1010 1110 1000                   (< 2: e = 15, sense desbordament)

\(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».