Els reals

Aquesta lliçó explica els valors que poden prendre les variables de tipus real (double), com es representen, i quines són les operacions que se’ls pot aplicar.

El tipus double

En C++, el tipus double representa el tipus dels nombres reals. Idealment, double es correspon al conjunt del reals ($\mathbb{R}$), tot i que, a la pràctica, els ordinadors limiten el nombre real més petit i més gran assolibles així com la precisió dels reals. Els valors reals es poden operar amb les operacions habituals (suma, resta, producte i divisió) i comparar entre ells.

Representació

Els valors reals es representen per literals com ara 3.1416, 0.001 i -45.0, és a dir, de la forma habitual. També es pot utilitzar la notació científica: 21.5e-3 representa $21’5 \cdot 10^{-3}$.

Amb independència de com es representin els nombres reals al codi o a l’entrada/sortida, l’ordinador desa internament els nombres reals utilitzant un determinat nombre de bits en coma flotant $\small[\mathbb{W}]$.

Operacions

Les operacions que es poden aplicar entre dos reals són la suma (amb l’operador +), la resta (amb l’operador -), el producte (amb l’operador *) i la divisió real (amb l’operador /). També hi ha disposible l’operació de canvi de signe (amb l’operador unari -). La operació de residu no existeix per als reals.

La taula següent mostra les operacions bàsiques entre reals:

Operador Operació
+ suma
- resta
* multiplicació
/ divisió real
- canvi de signe

Les operacions anteriors són les habituals entre reals. Per exemple, 3.5 + 9.0 val 12.5, 10.0/2.0 val 5.0, i 11.0/2.0 val 5.5.

La prioritat dels operadors aritmètics sobre els reals és l’habitual en matemàtiques: El producte i la divisió tenen prioritat sobre la suma i la resta. Sempre es poden utilitzar parèntesis per forçar que certes operacions s’apliquin abans que d’altres. Per exemple, 3.5 + 2.0 * 5.0 val 13.5 però (3.5 + 2.0) * 5.0 val 35.0.

A vegades, es barrejen operacions entre enters i reals. En aquests casos, els enters són convertits de forma automàtica a reals i el resultat és, doncs, un real. Així 3 + 4.5 es transforma automàticament a 3.0 + 4.5 i el resultat és, doncs, 7.5. Compte, 3 + 2.0 dóna com a resultat el real 5.0 i no pas l’enter 5.

A més, els reals també es poden comparar entre ells: Donats dos enters, es pot mirar si són iguals (amb l’operador ==), si són diferents (amb l’operador !=), si el primer és estrictament inferior al segon (amb l’operador <), si el primer és estrictament superior al segon (amb l’operador >), si el primer és inferior o igual al segon (amb l’operador <=), i si el primer és superior o igual al segon (amb l’operador >=).

La taula següent mostra les operacions bàsiques entre reals:

Operador Operació
== igualtat
!= diferència
< menor
> major
<= menor o igual
>= major o igual

Problemes de precisió

Com que els computadors enmagatzemen els nombres reals en coma flotant, aquests no sempre són exactes, sempre són una aproximació prou propera. Per exemple, el resultat de 0.1 + 0.2 dóna 0.30000000000000004 i ni 0.3 com hom esperaria. I, a sobre, aquests petits errors es propaguen a través dels càlculs successius!

Conseqüentment, les regles bàsiques de l’àlgebra no sempre es compleixen: Quan a i b són dos doubles, pot ser que a*b != b*a 😩.

Per això, moltes vegades cal que les operacions de comparació entre reals donin un petit marge de seguretat. Així, per saber si x i y són dos reals iguals, enlloc de preguntar si x == y, és més prudent preguntar si abs(x - y) < ε, on ε és un valor prou petit (en relació a x i y), com ara 1e-9 (una milionèsima).

Valors especials

Els nombres reals tenen alguns valors “especials” que són pràctics en determinades situacions:

El valor especial +∞ representa l’infinit positiu. És, per exemple, el resultat de dividir un real positiu entre zero (1.0 / 0.0). Anàlogament, el valor especial -∞ representa l’infinit negatiu. És, per exemple, el resultat de dividir un real negatiu entre zero (-1.0 / 0.0). Si es compara un infinit amb un valor finit, el resultat és l’esperat: Per exemple, 1.0 / 0.0 > 99.99 és cert i -1.0 / 0.0 < 1.0 / 0.0 també és cert. Quan tenen sentit, les operacions amb infinits també es poden aplicar: Per exemple, 5 + 1.0 / 0.0 dóna +∞.

El valor especial NaN (not a number) representa un valor real fruit d’un error. Per exemple, el resultat de dividir zero entre zero (0.0 / 0.0) és NaN i el resultat de sumar +∞ amb -∞ també és NaN (i no zero!). Els valors NaN no són mai iguals a ells mateixos.

També cal tenir en compte que el zero positiu i el zero negatiu són valors diferents (i el primer és més gran que el segón, és clar).

Confús? Potser sí, però tot està prou ben dissenyat (estàndard IEEE per l’aritmètica en coma flotant $\small[\mathbb{W}]$) i no cal preocupar-se’n massa.

El tipus float

C++ també disposa d’altres tipus per enmagatzemar reals. D’entre ells, sovint s’utilitza float, que té menys precisió que double, però que no és pas més ràpid en les màquines actuals. A més, a la llibreria estàndard les funcions solen ser per a doubles i no per a floats. Per tot això, entre float i double us recomanem d’utilitzar double.

El tipus float també representa el tipus dels nombres reals, però en general el tipus double ofereix més precisió que el tipus float i és igual de ràpid.

La llibreria <cmath>

La llibreria estàndard <cmath> sèrie de funcions matemàtiques sobre nombres reals com ara arrels quadrades, valors absoluts,… que extenen els operadors descrits. També defineix la funció isnan() per saber si un real és NaN.

La llibreria <limits>

La llibreria estàndard <limits> ofereix funcions que poden ser útils a l’hora de treballar amb nombres reals:

També es poden utilitzar per floats.


Fòrum







Lliçons.jutge.org
Jordi Petit, Salvador Roura
Universitat Politècnica de Catalunya, 2018

Prohibit copiar. Tots els drets reservats.
No copy allowed. All rights reserved.