Dijous, març 12, 2026
PROGRAMACIÓ

Nombres, operadors i conversions

Aquesta entrada se centra en els tipus numèrics bàsics de Python: enters (int), flotants (float), algunes funcions relacionades, operadors i conversions. No veurem encara decimal ni fractions però esmentarem en quins casos els podem necessitar.

Tipus numèrics principals en Python

int: enters

Els valors enters a Python no tenen un límit fix (com passava a C o Java amb int32 o int64). En principi, pots representar qualsevol nombre enter, positiu o negatiu, amb l’única limitació de la memòria disponible:

x = 42
y = -100
z = 10**100  # Un enter enorme

Python canvia internament de representació quan els enters creixen, però tu no has de fer res. Aquest comportament és molt útil en criptografia, finances o algoritmes matemàtics on es treballa amb enters grans.

float: números de coma flotant

Un float a Python és un número en notació decimal, que internament es representa com a doble precisió IEEE-754, igual que en la majoria dels llenguatges moderns.

a = 3.14
b = -0.00001
c = 1.0e6

El límit està en la precisió: un float representa números reals de forma aproximada. El més important és que no tots els decimals es poden representar exactament, i això genera errors comuns:

>>> 0.1 + 0.2
0.30000000000000004

No és un bug, és com funciona l’aritmètica binària amb decimals. No tots els números que s’ escriuen amb precisió decimal tenen una representació exacta en binari flotant.

Literals numèrics

Pots escriure números de diverses formes:

42       # decimal
0b1010   # binari
0o52     # octal
0x2A     # hexadecimal
1.5e3    # notació científica (1500.0)

Les lletres e o E indiquen notació exponencial en els float. No confondre amb **, que és l’operador de potència.

Operadors numèrics

Python té els operadors estàndard per treballar amb números. Hi ha alguns detalls que convé tenir clars.

Aritmètica bàsica

OperadorSignificatExemple
+Suma2 + 3
Resta4 – 1
*Multiplicació2 * 5
/Divisió (float)5 / 2 → 2.5
//Divisió entera5 // 2 → 2
%Mòdul5 % 2 → 1
**Potència2 ** 3 → 8

Python distingeix entre / i //. Aquesta diferència importa molt, sobretot si vens de C o JavaScript.

>>> 5 / 2
2.5
 
>>> 5 // 2
2
 
>>> -5 // 2
-3  # arrodoneix cap avall, no cap a zero

Aquesta última línia sol confondre. Python arrodoneix la divisió sencera cap al nombre més petit, no cap a zero. És coherent amb la definició matemàtica del pis (floor division), però no tots els llenguatges ho fan així.

Operadors bit a bit (només per a enters)

Aquests operadors només funcionen amb int i es fan servir més del que sembla: en sistemes embeguts, programació de baix nivell, estructures compactes, etc.

OperadorNomExemple
&AND bit a bit5 & 3 → 1
``OR bit a bit
^XOR5 ^ 3 → 6
~NOT bit a bit~5 → -6
<< Desplaçament a l’ esquerra1 << 3 → 8
>> Desplaçament a la dreta8 >> 2 → 2

Aquests operadors no converteixen tipus. Si fas 5 & 3.0 et retorna un TypeError.

Precedència d’ operadors

A la pràctica, molts errors venen d’assumir que Python avalua d’esquerra a dreta, sense tenir en compte la precedència d’operadors.

Aquí va un resum parcial (de major a menor precedència):

  • **
  • -x, +x, ~x (unaris)
  • *, /, //, %
  • +, –
  • <<, >>
  • &
  • ^
  • |
  • Comparacions (<, >, ==, etc.)
  • not
  • and
  • or

Exemple:

>>> 2 + 3 * 4
14  # no 20: * té més precedència
 
>>> -2 ** 2
-4  # perquè s'avalua com a -(2 ** 2), no com a (-2) ** 2
 
>>> (1 << 2) + 1
5

No cal memoritzar aquesta llista, però sí tenir en compte que l’ordre importa. Quan hi hagi dubtes, fes servir parèntesis.

Conversió de tipus (càsting)

Python permet convertir entre tipus numèrics explícitament amb funcions:

int(3.9)      # 3
float(5)      # 5.0
int("42")     # 42
float("1e-3") # 0.001

No hi ha conversió implícita en expressions com aquesta:

int("3.5")  # ValueError

Per convertir una cadena amb punt decimal a enter, cal fer doble pas:

int(float("3.5"))  # 3

La conversió implícita sí que passa en operacions mixtes:

>>> 3 + 2.0
5.0  # el resultat es promou a float

Aquesta promoció a float és automàtica si qualsevol dels operands ho és. Això pot generar errors subtils si estàs treballant amb enters grans i esperes que el resultat es mantingui exacte.

Comparacions i tipus mixtos

Python permet comparar tipus numèrics diferents:

>>> 3 == 3.0
True
>>> 3 < 3.1
True

Això funciona perquè int i float estan pensats per a interoperar. Tanmateix, amb altres tipus numèrics com Decimal, el resultat pot ser diferent:

from decimal import Decimal
 
>>> Decimal('3.0') == 3
False  # Tipus diferents, semàntica diferent

Per a evitar sorpreses, convé mantenir els tipus alineats en operacions crítiques, especialment en càlculs financers.

Arrodoniment i truncament

Python ofereix diverses formes d’arrodonir o truncar valors:

round(3.14159, 2)  # 3.14
int(3.9)           # 3 (truncament)
math.floor(3.9)    # 3
math.ceil(3.1)     # 4

La funció round té un comportament una mica diferent a l’esperat quan hi ha empats:

round(2.5)  # 2
round(3.5)  # 4

Esto se llama round half to even, o arrodoniment “a parell”. Es l’arrodoniment per defecte a Python (i a IEEE-754), perquè evita biaixos sistemàtics en sumar molts números.

Nombres negatius i mòdul

L’operació a % b a Python sempre retorna un resultat del mateix signe que el divisor:

>>> -7 % 3
2  # perquè -7 = (-3 * 3) + 2

Això pot xocar si véns de llenguatges on el signe del resultat segueix al dividend. Convé provar casos amb negatius si estàs treballant amb cicles, calendaris o divisions modulars.

Què passa amb els errors de precisió

Ja vam veure el cas clàssic:

>>> 0.1 + 0.2 == 0.3

False

Llavors què es fa si necessites comparar flotants?

Es fan servir comparacions amb tolerància:

import math
 
math.isclose(0.1 + 0.2, 0.3, rel_tol=1e-9)

En càlculs crítics, no facis servir  == amb floats. Fes servir math.isclose o, millor, fes servir decimal. Decimal si necessites precisió decimal exacta (per exemple, per a facturació).

Errors típics en treballar amb números a Python

1. Assumir que int() arrodoneix

>>> int(3.9)
3

Això no arrodoneix: trunca cap a zero. Si necessites arrodonir, fes servir round():

>>> round(3.9)
4
>>> round(-3.9)
-4

I si necessites truncar explícitament cap avall o cap amunt:

import math
 
math.floor(3.9)   # 3
math.ceil(3.9)    # 4
math.trunc(3.9)   # 3

2. Comparar floats amb ==

Com ja hem esmentat, fer servir == amb flotants és problemàtic:

>>> 0.1 + 0.2 == 0.3
False

El correcte:

math.isclose(0.1 + 0.2, 0.3, rel_tol=1e-9)

I si el número és molt petit, és millor fer servir abs_tol:

math.isclose(1e-10, 0.0, abs_tol=1e-12)

3. Fer servir float per a càlculs financers

Evita-ho, llevat que els muntants siguin irrellevants. Fes servir decimal. Decimal:

from decimal import Decimal
 
Decimal('0.1') + Decimal('0.2') == Decimal('0.3')  # True

Això et dona resultats exactes i configurables.

Funcions útils al mòdul math

Python inclou funcions matemàtiques bàsiques en el mòdul math, totes per a float:

import math
 
math.sqrt(16)      # 4.0
math.sin(math.pi)  # quasi 0.0
math.log(100, 10)  # 2.0
math.exp(1)        # e ≈ 2.718
 
math.isfinite(x)
math.isnan(x)
math.isinf(x)

Tots els resultats són de tipus float. math no serveix per a enters grans ni per a treballar amb Decimal (per això hi ha el mòdul decimal, que té la seva pròpia API).

Alguns comportaments poc intuïtius

Divisió entera amb números negatius

Ja ho vam veure, però val la pena repetir-ho perquè causa errors lògics:

>>> -5 // 2
-3
>>> -5 % 2
1

Perquè (-3 * 2) + 1 = -5. El resultat de % sempre té el mateix signe que el divisor.

Potències negatives amb enters

>>> 2 ** -3
0.125

El resultat és float, encara que el número base sigui enter. Això importa si estàs esperant int en una funció.

Com es comporten int() i float() amb cadenes?

Depèn de la cadena:

>>> int("42")
42
>>> float("3.14")
3.14
>>> int("3.14")
ValueError

No pots convertir directament “3.14” a int. Cal passar per float() primer.

També has d’evitar confiar en entrades d’usuari sense validació:

try:
    x = int(input("Número: "))
except ValueError:
    print("Això no és un sencer vàlid.")

Com detectar el tipus de número que estàs fent servir

Python no distingeix visualment entre 3 i 3.0 en molts casos, però pots verificar amb type() o isinstance():

type(3)         # <class 'int'>
type(3.0)       # <class 'float'>
 
isinstance(3, int)     # True
isinstance(3.0, float) # True

Això és útil quan reps arguments que poden ser de diferents tipus i necessites tractar-los diferent.

Quin tipus de nombre s’ obté en operacions mixtes

Python promou automàticament al tipus de major precisió:

Operant 1Operant 2Resultat
intintint
intfloatfloat
floatfloatfloat
>>> type(2 + 3.0)
<class 'float'>

La promoció passa fins i tot si el resultat podria representar-se com a int. Si necessites mantenir sencers exactes, assegura’t de no barrejar tipus sense voler.

Què passa amb valors especials: NaN, inf, -inf?

Pots generar-los així:

float('inf')
float('-inf')
float('nan')

I comparar-los:

math.isinf(float('inf'))   # True
math.isnan(float('nan'))   # True

Però compte:

>>> float('nan') == float('nan')
False

Això és per definició: NaN no és igual a res, ni tan sols a si mateix. Per a detectar-ho, sempre fes servir math.isnan().

Exemple pràctic: mitjana d’ una llista mixta

Vegem un cas real: calcular la mitjana d’una llista que pot contenir sencers i flotants, i gestionar el cas buit.

def promedio(llista):
    if not llista:
        return None
    total = sum(llista)
    quantitat = len(llista)
    return total / cantidad
promedi([1, 2, 3])        # 2.0
promediquantitat([1.0, 2, 3.5])    # 2.166...
promedi([])               # None

El resultat és sempre float, perquè la divisió amb / el força. Si vols que sigui int si tots els valors ho són i el resultat és exacte, necessites més lògica, però rarament convé complicar-ho.

Què convé recordar de tot això

  • int en Python no té límit fix, però float sí que té precisió limitada.
  •  arrodoneix cap avall, no cap a zero.
  • % retorna el residu amb el signe del divisor.
  • No compares float amb == si pots evitar-ho.
  • No fas servir float per a diners.
  • Usa math.isclose() si necessites comparar amb tolerància.
  • Les operacions amb tipus mixtos promouen el tipus de major precisió.
  • El resultat d’int() trunca, no arrodoneix.

I si necessito més precisió o comportament exacte?

Llavors no facis servir float. Python té altres dues opcions:

  • decimal. Decimal: per a càlculs exactes amb decimals, configurable, ideal per a diners o càlculs comptables.
  • fractions. Fraction: per a fraccions exactes, com 1/3, 5/7, etc.

Aquestes no es cobreixen en aquesta entrada, però formen part de l’ecosistema estàndard i val la pena explorar-les si la teva aplicació depèn de càlculs precisos.

Deixa un comentari

L'adreça electrònica no es publicarà. Els camps necessaris estan marcats amb *