Notes and Talks/UJEP/PRG1/02

Desetinná čísla, modul math, vstup a výstup, formátované řetězce

Čísla typu float

Desetinná (reálná) čísla třídy (typu) float jsou „nepřesná“, to jest: jsou přesná, ale jen pro určité hodnoty, které jsou realizovatelné v hardware. Výsledky výpočtů mohou být systémem zaokrouhleny na nejbližší reprezentovatelné číslo.

Nepoužívejme je proto pro přesné výpočty a přesná porovnávání!

Příklad:

python5/7 == (2/7) * (5/2)

Mělo by být True, ale je False. Proč?

python5/7

0.7142857142857143

python(2/7) * (5/2)

0.7142857142857142

Rozdíl:

python5/7 - (2/7) * (5/2)

1.1102230246251565e-16 velmi malé číslo (numerická zaokrouhlovací chyba)

Zde bylo číslo vypsáno v tzv. vědeckém zápisu (scientific notation), ve formátu mantissa a exponent.

Výhodou čísel float je jejich velký rozsah, nevýhodou jejich omezená přesnost.

float čísla lze přibližně porovnat např. takto (abs je nutné!!):

pythonabs((5/7) - ((2/7) * (5/2))) < 1e-10

To jest, ptáme se: je rozdíl čísel dostatečně malý, neboli: jsou si čísla dostatečně blízká?

Modul math má pro takovéto porovnání funkci isclose():

pythonmath.isclose(5/7, 2/7 * 5/2)

Řádkový výstup

Pro řádkový výstup je k dispozici vestavěná funkce print(): w3schools, docs.python

print() umí vypsat hodnoty mnoha (všech?) typů:

pythonprint(3)
print(3.2)
print(3/2)
print('3/2')

Lze také vypsat několik hodnot najednou. Jednotlivé hodnoty jsou zadány jako tzv. pozicionální argumenty (positional arguments), a jsou automaticky odděleny mezerou:

pythonprint(3, 3.2, 3/2, '3/2')

Oddělovač (obsah mezi vypsanými hodnotami, separator) lze specifikovat pomocí tzv. pojmenovaného argumentu (named argument) sep:

pythonprint(3, 3.2, 3/2, '3/2', sep=' : ')

print autovaticky ukončí řádku tím, že na její konec přidá (neviditelný) znak pro přechod na novou řádku (newline, NL).

pythonprint('čísla: ')
print(3, 3.2, 3/2, '3/2')

Ukončení řádky lze specifikovat pomocí pojmenovaného argumentu end:

pythonprint('čísla: ', end='') # no newline
print(3, 3.2, 3/2,'3/2')
print('čísla: ', end='// ') # custom ending
print(3, 3.2, 3/2,'3/2')

A v takovém případě lze NL, přechod na novou řádku vložit pomocí tzv. „escape“ sekvence \n:

pythonprint('čísla: ', end='//\n')
print(3, 3.2, 3/2, '3/2')

Řádkový vstup (opakování)

Vstup řádky textu se provede vestavěnou funkcí input(): w3schools, docs.python

pythonprint('Enter your name:') # prompt
name = input()
print('Hello,', name)

Výzvu (prompt) lze vložit jako argument přímo do volání funkce input():

pythonname = input('Enter your name: ')
print('Hello,', name, end='!\n') # why 'end'?

input() vrací objekt typu str (string, řetězec):

pythontype(input('Enter your name: '))

Vestavěná funkce int() se pokusí převést svůj argument (řetězec, nebo cokoli jiného) na číslo (objekt) typu int:

pythonint(3.2)
pythonint('3')

Ale ne:

pythonint('3.0')

Vestavěná funkce float() se podobně pokusí převést zadaný argument na objekt typu float:

Tohle už jde:

pythonfloat('3.0')

A tohle také:

pythonint(float('3.0')) # does int() truncate or round the float?

Nebo také (pokud zadáte správný vstup):

pythonint(input('Enter an int: '))

Formátování řetězců

Řetězce lze spojovat operátorem +:

pythonname = input('Enter your name:')
text = 'Hello, ' + name + '!'
print(text) # or, directly: print('Hello, ' + name + '!')

Použití stejného operátoru pro rozdílné operace podle typu operandů (sčítání čísel, spojování řetězců) je tzv. přetížení operátoru (operator overloading).

Od verze Pythonu 3.6 lze použít tzv. f-string (formátovaný řetězec, formatted string, řetězcovou interpolaci, string interpolation). Proměnné se vkládájí uzavřeny ve složených závorkách {} (docs.python):

pythonname = input('Enter your name:')
print(f'Hello, {name}!')

Do složených závorek lze vložit i celý výraz:

pythona = 2
b = 3
print(f'a = {a}, b = {b}, a + b = {a+b}')

Porovnávání a podmíněný výraz (ternární operátor)

Hodnoty lze porovnávat:

pythona = 3
b = 4

# čísla
print('a == 3:', a == 3)
print('a != 3:', a != 3)
print('a < 3:',  a < 3)
print('a <= 3:', a <= 3)
print('a > 3:',  a > 3)
print('a >= 3:', a >= 3)
print('a < b:',  a < b)

# řetězce
print("'a'=='b'", 'a'=='b')
print("'a'<='b'", 'a'<='b')

Výsledkem porovnání je pravdivostní (booleovská) hodnota True nebo False (typu bool):

Podle pravdivostní hodnoty lze podmíněným výrazem vybrat jednu ze dvou hodnot:

python3 if True else 4
python3 if False else 4
pythona = 3
b = 4

menší = a if a<b else b
print('menší je', menší)

menší = 'a' if a<b else 'b'
print('menší je', menší)

Příklad z LOTRu:

pythonFr = 'Frodo'
FrAge = 50

Gd = 'Gandalf'
GdAge = 2000

print(f'{Fr} is {FrAge} and {Gd} is {GdAge}.')
print(f'{Gd if FrAge<GdAge else Fr} is older and therefore wiser.')

Booleovská algebra (boolean algebra)

V Booleovské algebře jsou

pythonprint(type(False), type(True), 3<4, type(3<4)) # etc.
print(3<4 and 4<5)
print(3<4 and 3>4)
print(3<4 or 3>4)
print(not 3>4)