El propòsit inicial dels computadors era computar números.

Introducció

De de fa més de 400 anys una computadora era una persona que calculaba números:

Una part de la teva infància ha estat aprenent a fer càlculs amb números, i molts cops t'has preguntat que perquè has d'apendre aquestes coses si el teu mòbil té una calculadora que ho fa molt millor que tu.

El mateix van pensar les empreses, els governs i els enginyers, i per això van crear els primers computadors mecànics.

A continuació tens la imatge de l'ENIAC dels anys 40, molt gran, però molt menys potent que el teu mòbil:

A principis de 1960 ja existien les primeres calculadores comercials.

A continuació tens la imatge del IBM 608:

Aquestes màquines mai s'equivoquen, no es posen malaltes, no protesten, etc.

I el que passa sempre, ja pots despedir a molta gent que no necessites i que s'ha de pagar bé perqué preparar una calculadora "humana" porta molt de temps.

Una professió centenària va desaparèixer 😔.

Doncs comencem des del principi, i recorda ..

Encara que pensis que una computadora és per jugar, veure películes, etc. radera d'aquests programes hi ha moltes operacions matemàtiques!

Entorn de treball

Per treballar amb Python farem servir un entorn Linux.

Crea una màquina Uubnut tal com s'explica a Windows Subsytem for Linux (WSL):

> wsl --update
> wsl --install -d ubuntu

A continuació inicia l'interpret de Python en mode interactiu:

$ python3

Per sortir de l'interpret de Python escriu exit() o Ctrl-D:

>>> exit()

Números

Python és un llenguatge que fan servir els enginyers, científics i empreses.

Ells necessiten treballar amb números de manera fàcil i precisa sense tenir que estar sempre pendent de com funcionen en realitat els números en un computador.

Perqué si no treballes correctament amb els numeros d'un computador pots tenir un resultat erroni, i a tu et pot semblar que tampoc hi ha per tant, sobretot quan no estas conforme amb el resultat d'una avaluació.

Però pots estar completament segur que a un enginyer o a un científic no pensarà el mateix.

Com que el tu també programes amb Python, també pots estar tranquil al respecte, però pensa que en altres llenguatges de programació la cosa no és tan fàcil.

El que fa funcionar un computador és la CPU, que té una ALU, i l'ALU té un circut per processar opearacions amb nombres enters (int) i reals (float).

Enters

Els enters són tots aquells números que no tenen decimals.

Per exemple:

  • Un 2 és un int
  • Un 2.0 és un float.

Tots dos representen el mateix número, però no són el mateix:

>>> type(2)
<class 'int'>
>>> type(2.0)
<class 'float'>

Amb type pots preguntar a Python que es cada cosa i ja veus que et diu que són de classe (class) diferent.

Segur que adivines com es distingeix un int d'un float ...

... el float sempre té un . al final i potser alguns números a continuació.

Així de fàcil, Python és un llenguatge pragmàtic:

>>> type(2.)
<class 'float'>

Si pots, és millor treballar amb enters (int) perquè ...

... les operacions amb nombres enters (int) són més ràpides i els números mai tenen problemes de precisió.

Com hem explicat al principi del propòsit original d'un computador és fer operacions matemàtiques.

Els operadors +, - i * s'utilitzen per realitzar operacions aritmètiques simples amb enters.

A continuació tens uns exemples:

>>> 2 + 2
4
>>> 3 - 6
-3
>>> 3 * 4
12

Si et fixes falta la divisió.

El motiu és que la majoria de les vegades el resultat de la divisió d'un número enter per un número enter no és pot representar amb un número enter si vols conservar la part dels decimals.

Per exemple, 5 / 2 és igual a 2.5, i és un float (un decimal) perquè té el punt.

La unitat d'enters de l'ALU no té implementat la divisió d'enters per aquest motiu tant obvi: només pot treballar i representar números enters.

El que fa Python en aquest cas es convertir els int en float i realitzar la divisió amb la unitat de floats de l'ALU.

I el resultat com es obvi sempre serà un float tal com pots veure a continuació:

>>> 2 / 2
2.0

Potser pots pensar que:

  • És una mica absurd escriure un 2 com 2.0: Python afegeix el 2.0 perquè tinquis clar que el resultat és un float no un int.

  • Python podria ser més "intel.ligent" i tornar com a resultat un 2 (per tant un int) en aquest cas concret: és una solució més fàcil, elegant, ràpida i predictible tornar sempre un float.

Si només vols la part sencera d'una divisió pots utilitzar l'expressió // i si vols la resta l'expressió %:

>>> 8 // 6
1
>>> 8 % 6
2

Pots veure que el resultat sempre es un enter (int).

Per calcular potències utilitza l'operador **:

>>> 2 ** 2
4
>>> 2 ** 4
16

Amb l'ús de parèntesis () pots agrupar operacions per especificar un ordre explícit per resoldre-les:

>>> 2 + 3 * 4
14
>>> (2 + 3) * 4
20

Reals

Com ja deus saber els números enters són útils fins a cert punt.

Per això van inventar els nombres racionals, que segur no t'agraden massa, i els reals (o decimals) que t'agraden més perquè tu no fas les operacions sinò una calculadora.

Els números reals (float) tenen problemes de precisió, però poden representar números amb decimals 🤔.

En qualsevol tipus d'operació, si hi ha un float pel mitg, el resultat sempre és un float!.

>>> 2 + 2.0
4.0

I l'operació s'executa en el circuit de floats de l'ALU.

El motiu és que un int es pot representar amb més o menys precició com un float, però al revés en la majoria de casos no és possible.

Per exemple, tens una prèstec de 5000 euros al 5% d'interés.

Al final d'any quan m'has de pagar?

>>> 5000 * 0.05
250.0

Has de pagar 250 euros, o 250.0 euros en lleguatge d'ordinador, però si utilitzes llenguatge d'ordinador amb persones a la vida real pensaran que potser ets una mica ...

Si decideixo representar 0.05 com un enter que escullo un 0 o un 1?

>>> 5000 * 0
0
>>> 5000 * 1
5000

Segur que tu prefereixes representar el 0.05 com un 0 i el banc com un 1.

El que fa Python, com és lògic i segur que ara estas d'acord, és convertir 5000 en 5000.0 (un float) i tornar el resultat com un float.

I això ho fa sempre tal com demostra aquest exemple:

>>> 1 + 2.0
3.0

Lógica de Python: Si algun operand és un float, convertir tots els operands a float (i el resultat és un float).

Per cert, per si de cas ...

Totes les opeacions que es fan amb enters també es fan amb reals: +, -, etc.

Variables

Una variable és un nom que ens permet guardar algún valor.

>>> x = 4 + 2
>>>

On està el resultat de l'operació que abans aparexia a continuació?

Doncs enlloc d'imprimir el resultat en pantalla, s'ha guardat a la variable x:

>>> x
4
>>> x
4

I com sap Python que x és una variable i no un número?

Doncs perquè Python no permet que el nom d'una variable comenci per un número:

>>> 3x = 3
  File "<stdin>", line 1
    3x = 3
    ^
SyntaxError: invalid decimal literal
>>>

I t'ho explica bé, però en anglès.

Si no entens el que posa, utilitza un traductor per traduir les explicacions de Python.

Però a part d'això, el nom de la variable pot tenir números:

>>> x3 = 3
>>> x3
3

Lògica de Python. Si la primera lletra és un número, doncs és un número, sino, és una variable.

>>> x3 + 2
5
>>> 3x + 2
  File "<stdin>", line 1
    3x + 2                                                                ^
SyntaxError: invalid decimal literal
>>>

Segur que per tu 3x no és un número, però per Python és un número mal escrit.

La gent pensa que els ordinadors són tontos quan fan coses com aquestes, enlloc de donar la raó a Python.

Com has vist en l'exemple d'abans una variable és pot utilitzar en operacions aritmètiques, i es fa servir el valor de la variable no pas el nom de la variable.

Ep! Això ja ho saps de matemàtiques.

>>> a = 3
>>> b = 5
>>> a + b + 4
12

I perqué li diem variable?

Doncs perqué el seu contingut no és fixe, sinò que el pots modificar quan vulguis.

>>> x = 8
>>> x +2
10
>>> x = 20
>>> x + 2
22
>>> x = -4.0
>>> x + 2
-2.0

I quin ús tenene les variables?

Molts. Ara en veurem alguns.

Acumulador

Una variable va molt bé per anar acumulant els resultat de vàries operacions.

Per exemple, per saber la mitja de les notes dels alumnes.

Ja ser que les pots sumar totes de cop amb Python perqué caben perfectament a la pantalla de l'ordinador, i pots revisar que no t'has equivocat, però amb la calculadora del Windows no passa el mateix, per posar un exemple.

Com que ara ja has descobert que és més fàcil utilitzar Python que la calculadora ...

>>> notes = 4.56 + 3.45 + 9.54 + 3.45 + 6.89 + 5.67
>>> notes
33.559999999999995
>>> notes = notes + 2.45 + 7.78 + 8.65 + 5.33 + 4.55
>>> notes                                                             62.31999999999999
>>> notes = notes / 10
>>> notes
6.231999999999999
>>>

Tenim 10 alumnes, i la mitja de les notes de la classe és 6.232.

Però Python diu que la mitja és 6.231999999999999 no pas 6.232, i abans havies dit que Python no s'equivoca !

També et vaig dir que si podem és millor utilitzar ints que floats perquè els floats tenen un lleuger problema de precisió com pots veure en aquest exemple.

A continuació repetirem el mateix exemple, però afegint una nota una a una:

>>> notes = 4.56
>>> notes = notes + 3.45
>>> notes = notes + 9.54
>>> notes
17.549999999999997

Però això és molt pesat d'escriure ! Tens raó.

Com que és una operació molt habitual anar fent operacions amb una variable i guardar el resultat en la mateix variable, enlloc de + pots utilitzar l'operador +=.

>>> notes += 6.89
>>> notes += 5.67
>>> notes /= 5
>>> notes
6.022

També hi ha l'operador =-, =*, etc.

A més de ser una sintaxi més curta expresa millor el que s'està fent.

Aquestes dues sentències fan el mateix, però la primer expresa millor el que s'està fent.

>>> x *= 3
>>> x = x * 3

Constant

Per calcular l'area d'un cercle has d'utilitzar la fòrmula πr², on r es el radi del cercle y π és el número Pi.

L'area d'un cercle de diametre 5 és ...

>>> 3.141592653 * (5 ** 2)
78.539816325

Segur que recordes de memòria el número Pi i no t'importa escriure'l tantes vegades com sigui necessari.

Si tenim que calcualr moltes vegades l'area d'un cercle és millor guardar el nombre Pi en una variable, i utilitzar la variable enlloc del número.

>>> PI = 3.141592653
>>> PI * ( 2 ** 2)
12.566370612
>>> PI * ( 8 ** 2)
201.061929792                                                         >>> PI * ( 13 ** 2)
530.929158357

D'aquesta manera és més fàcil i queda clar que PI és un número amb un significat especial!

Si et fixes PI està escrit en majúscules.

Els programadors de Python escriuen en majúscules aquelles variables que guarden coses que tenen valor per elles mateixes i que no s'han de modificar: les constants.

Per cert, Python distingeix entre majúscules i mínúscules.

Per tant, PI i pi no són el mateix:

>>> PI
3.141592653
>>> pi
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'pi' is not defined. Did you mean: 'PI'?
>>>

Llegibilitat

Quan escrius codi és normal posar espais perquè el codi sigui més llegible:

>>> 2 + 4
6
>>> x = 80
>>> x
80

Però a Python els espais tant li fa, els ignora !

Per ell totes aquestes sentències són el mateix:

>>> 2      +          4     +         -       5
1
>>> 2+4+-5
1
>>> 2 + 4 + -5
1

Però per nosaltres l'última sentència és la més fàcil d'entendre.

Però hi ha una excepció!

Una sentència no pots començat amb espais en blanc:

>>>     3 + 3
  File "<stdin>", line 1
    3 + 3
IndentationError: unexpected indent

Ha Algoritme explicarem el motiu.

La llegibilitat és important entre altres coses perquè Pyhton, al igual que les màtemàtiques, fa servir el mateix simbol per l'operació de resta que per indicar un número negatiu, el - (igual pasa amb +).

String

A més de int i float, en Python també tenim el tipus str.

str és una sequènica de caràcters (lletres, números, espais en blanc, etc.) que no tenen cap significat per al programa i que es tracten com un bloc.

Quan Python troba un " sap que el que ve a continuació no són instruccions, i quan troba el " de tancament sap que ha acabat el text i ho guarda com un str.

A continuació tens exemples de diferents strs:

>>> type("hola")
<class 'str'>
>>> type("33")
<class 'str'>
>>> type("x")
<class 'str'>
>>> type("")
<class 'str'>                                                         
>>> type("En un lugar de la Mancha, de cuyo nombre no quiero acordarme, no ha mucho tiempo que vivía un hidalgo de los de lanza en astillero, adarga antigua, ...")
<class 'str'>
>>> type("こんにちは世界")
<class 'str'>

I l'str ha d'acabar sempre amb ", sino Python diu que no, encara que per nosaltres sigui un string:

>>> type("barcelona
  File "<stdin>", line 1
    type("barcelona
         ^
SyntaxError: unterminated string literal (detected at line 1)

Amb la instrucció print, podem mostrar textos literals:

print("Hola a tothom!")

I també els valors de variables o constants:

curs = "2024/2025"
LLICENCIA = "CC-BY-SA-4.O"
print("Hola 😊!")
print(curs)
print(LLICENCIA)

Resultat:

Hola 😊!
2024/2025
CC-BY-SA-4.0

Aquesta forma de mostrar els resultats és bona, però si volem mostrar literals i variables o constants en una sola linia, Python proporciona una tècnica més potent, els F-String (Format String), disponibles des de Python 3.6

En versions anteriors a Python 3.6 ho podiem (i encara podem) fer de la següent manera:

nom = "Jose"
print("Com estàs",nom,"?")

Amb f-string podem combinar literals i variables d'aquesta manera:

curs = "2024/2025"
nom = "Adriana"
print(f"Hola 😊! Benvinguda al curs {curs}, {nom}.")
Hola 😊! Benvinguda al curs 2024/2025, Adriana.

Quan posem print(f") ja avisem a l'intèrpret que apart d'imprimir únicament literals o variables, formatejarem la sortida per mostrar-ho tot en una mateixa sentència.

f-string també ens permet realitzar operacions numèriques, conversions de tipus, arrodoniments...

## Operacio amb f-string
print(f"2**10={2**10}")
## Conversió
memoriaGB = "12.7"
print(f"{float(memoriaGB)*1024} MB")

Resultat:

2**10=1024
13004.8 MB

Amb la funció float() hem convertit el string a número decimal. Això és molt útil, ja que en moltes ocasions podem rebre les dades amb tipus stringencara que siguin float i cal convertir-les si volem operar-les.

## Arrodoniment amb f-string
PI=3.141592653
print(f"{round(PI,4)}")
print(f"{PI:.4f}")

Resultat:

2**10=1024
13004.8 MB

Fixa't que la instrucció print(f"{PI:.4f}") fa el mateix que print(f"{round(PI,4)}").

Activitats

1.- Escriu aquesta sentència de manera que es puguin entendre fàcilment:

+4++6-+6+-10

+4 + +6 - +6 + -10

2.- Mostra el següent text, usant la tècnica de l'f-string i les següents variables:

Variables

usuari="usuari1"
espai=125.5999

Text: "L'usuari alumne1 té 125.60 MB d'espai lliure"

usuari="alumne1"
espai=125.5999
print(f"L'usuari {usuari}{espai:.2f} MB d'espai lliure")

Errors

Quan estas aprenent és molt important cometre errors de forma deliberada perqué d'aquesta manera t'ajuda a recordar el que estás aprenent i, potser més important encara, aprens a entendre els missatges d'error. És millor cometre ara errors de manera deliberada que més tard sense voler.

També és molt important que entenguis els missatges d'error en anglés. Si tens problemes pots utilitzar el traductor de Google.

1.- NameError

>>> 2 * z
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'z' is not defined

La variable z no existeix.

Si vols utilitzar la variable z en una expresió, primer l'has de definir:

>>> z = 5
>>> 2 * z
10

2.- SyntaxError

>>> 03 + 4
  File "<stdin>", line 1
    03 + 4
    ^
SyntaxError: leading zeros in decimal integer literals are not permitted; use an 0o prefix for octal integers

3.- ZeroDivisionError

>>> 4/(2+2+-4)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ZeroDivisionError: division by zero