Počítač si za mě pamatuje

Z Základy informatiky pro střední školy
Přejít na: navigace, hledání

Počítač za mě počítá · Počítač za mě řeší nudné úkoly

ikona boxu
Co se naučíš:

Používat proměnné k ukládání informací během práce programu.

ikona boxu
Úloha: Obsah trojúhelníku

Trojuhelnikove pole osivo.svg

Farmář by rád poprvé osel své malé pole. Potřebné množství osiva záleží na ploše. Pole má tvar trojúhelníku. Farmář už pole oplotil, takže zná délky stran: 46, 78 a 86 metrů. Najdeš vhodný způsob, jak zjistit plochu k osetí?

ikona boxu
Délky stran na obrázku

Délky na obrázku neodpovídají délkám v zadání. To je záměr. Kdo nesrovnalost odhalí, zaslouží ocenit. Nakonec ji odhalí i farmář a my zjistíme, že je díky proměnným vcelku snadné výsledek přepočítat.

ikona boxu
Nápověda
ikona boxu
Chcete vědět víc?

Pomalé vysvětlení vzorce uvidíš v tomhle videu. Umožní ti řešit zajímavé úlohy.

Bojuješ s hledáním výšky trojúhelníku? Možná potřebuješ připomenout, že existuje Heronův vzorec.
Nezapomeň správně uplatnit, co znáš z předchozí kapitoly (např. závorky).
K odmocňování využij modul math.

Řešení

Heronův vzorec se zjednodušeně zapisuje takto:

, kde a jsou strany toho trojúhelníku.
V celé kráse tedy vzorec vypadá takto (dá se samozřejmě upravit i jinak):

ikona boxu
Výpočet na dva kroky s mezivýsledkem

Přehlednější je nejdřív spočítat polovinu obvodu ((46+78+86)/2), a tento mezivýsledek (103) pak dosadit do vzorce a do vzorce pak dosadit tu (math.sqrt( 105*(105-46)*(105-78)*(105-86) )). Je to celkově kratší, ale vyžaduje to dva kroky pokaždé, když budeme chtít takový výpočet provést.

Do interaktivní konzole tedy budeme chtít zadat dost ošklivý řetězec:

math.sqrt( ((46+78+86)/2)*((46+78+86)/2-46)*((46+78+86)/2-78)*((46+78+86)/2-86) )

To je sice pořád lepší, než výpočet s kapesní kalkulačkou či mobilem, ale v našem století bychom mohli očekávat něco vícOčekávali bychom třeba online přístup do katastru nemovitostí. Dovedeš v něm zjistit, na kolika m2 vlastně bydlíš? Pro potřeby naší úlohy teď ale předstírejme, katastr není k dispozici.. Jak vidno, při složitějších výpočtech nám dosavadní znalosti přestávají stačit. K výsledku dojdeme, ale velmi pracně. Přitom výpočet obsahu trojúhelníku ani není nějak zvlášť náročný úkol.

Možná tě napadlo, že při ručním počítání lze opakovaně využít hodnotu s (polovinu obvodu), a tím si trochu práce ušetřit. Umět si uložit nějaké mezivýsledky by se jistě hodilo i na počítači.

Otazník
Zamysli se a odpověz:

Někteří z vás možná ještě používají kapesní kalkulačku. Nejspíš na ní mají tlačítka jako M+, M-, MR, MC (a leckterá kalkulačka na telefonu je má taky). K čemu jsou?

Proměnná

K dočasnému uchování informací v programování slouží proměnné. Jejich výhodou oproti M-tlačítkům na kalkulačce je, že jich můžeme používat víc zároveň, můžeme je smysluplně pojmenovat, a hodnoty nemusí být vždy jen číselnéI když jak se to vezme, že.... Proměnnou v Pythonu „vyrobíme“ tak, že k nějakému(dosud nepoužitému) jménu přiřadíme hodnotu operátorem = (znak „rovná se“).

Příklad:

Replit promenna.png

Do proměnné a je uloženo celé číslo 46. Po zadání samotného názvu proměnné do konzole Python vytiskne její hodnotu. Proměnnou můžeme použít také přímo v nějakém výpočtu.

Nech konzoli provést příkaz a = 46. Stalo se něco? Nevypadá to tak (konzole nic nevypsala), ale stalo. Konzole si teď pod názvem a pamatuje délku strany a, tedy 46Že jde o metry, konzole neví, je to prostě číslo.. Snadno se o tom přesvědčíš prostým zadáním a. Odteď kdykoliv, když použiješ a tam, kde by jinak byla hodnota, použije se hodnota proměnné.

Můžeš tedy pokračovat. Zadej délky zbylých stran do proměnných b a c. Díky tomu budeš moci dále postupovat stručněji. Také se už nebudeš muset soustředit na konkrétní hodnoty. Polovinu obvodu i obsah už můžeš počítat nezávisle na konkrétních hodnotách, pouze pomocí proměnných. Zkus to!

import math
a = 46
b = 78
c = 86
PulObvodu = (a+b+c)/2
Obsah = math.sqrt(PulObvodu * (PulObvodu - a) * (PulObvodu - b) * (PulObvodu - c))

Po provedení uvedeného kódu je v proměnné Obsah uložen vypočtený obsah trojúhelníkového pole. Hledaný obsah trojúhelníka, tedy plocha pole k osetí je přibližně 1783 m2. Výpočet pomocí proměnných je zjevně úspornější, přehlednější a srozumitelnější.

ikona boxu
Představa paměti počítače

Jestli si představujete paměť počítače jako obrovské množství zásuvek, v nichž jsou uložena data, proměnnou si můžete představit jako nálepku označující zásuvku jménem. Když si chci něco uložit, dám to do zásuvky. Abych se k datům mohl vrátit, musím vědět, ve které zásuvce jsou. Proto zásuvku označím jménem a místo dat si pamatuju to jméno, což bývá mnohem jednodušší. Navíc pak můžu pracovat způsobem „sečti hodnoty v těchto dvou zásuvkách a výsledek ulož do zásuvky označené tímto jménem“ a vytvářet tak obecnější postupy.

Pozor na omezení této představy. V zásuvkách jsou data, nikoliv nějaký materiál. Přečtením obsahu zásuvky a uložením téhož (zkopírovaného) obsahu do zásuvky s jiným jménem se původní zásuvka nevyprázdní. Ze stejného důvodu nelze srovnávat „krádež filmu“ (nebo jiných dat) s krádeží třeba automobilu. Ukradená data „původnímu majiteli“ nechybí.

Definice proměnné se v různých jazycích mírně liší, ale obecně jde o symbolické pojmenování hodnoty, abychom s tou hodnotou mohli dále nakládat. Podobně pracujete s adresami buněk v tabulkovém procesoru: do vzorce píšete adresu buňky, pro výpočet se pak použije hodnota v buňce. Víš, že buňky jdou i pojmenovávat, a jméno pak lze použít místo adresy?

S principem proměnné se pracuje např. i ve smlouvách. Na začátku jsou určeny a pojmenovány smluvní strany, předmět smlouvy apod. Dále už se pracuje pouze s těmi jmény: kupující, prodávající, objednatel, dodavatel, zboží, zaměstnavatel, zaměstnanec, atd. Výhoda je zřejmá: smlouvy jsou stručnější, srozumitelnější a znovu použitelné prostou výměnou údajů na začátku.

ikona boxu
Proměnné v informatice vs. v matematice

Proměnná v našem programování je něco jiného, než neznámá v matematice. Proměnná může v průběhu výpočtu měnit svou hodnotu. V matematice by nám takové chování nadělalo nepořádek. Navíc v matematice jsme zvyklí na jednopísmenná označení. Programátoři mají ovšem raději, když název proměnné jasně vyjadřuje její význam. Programům lze potom mnohem snáze rozumět, což za tu trochu psaní navíc rozhodně stojí. Srovnej třeba zápisy vs. Obsah = (Zakladna*Vyska) / 2. Na druhé straně se při pojmenování proměnných omezujeme na latinku, případná řecká či jiná písmena vypisujeme, např. Alfa = 180 - Beta - Gama.

ikona boxu
Úloha: Hodinky nejsou holinky

Odhadni, co se vytiskne po spuštění tohoto kódu, a svůj odhad ověř:

DelkaHranyKrychle = 4
ObsahStenyKrychle = DelkaHranyKrychle * DelkaHranyKrychle
ObjemKrychle = ObsahStenyKrychle * DelkaHranyKrychle
print(ObjemKryhle)

Shoduje se tvůj odhad s výsledkem? Vysvětli, co se stalo.

ikona boxu
Nápověda

U chybových hlášení v Pythonu ti nejvíc informace podá poslední řádek. Z něj zjistíš, co se Pythonu nelíbí.
Kromě toho můžeš v chybové hlášce zjistit, kde se Python zastavil. To ti může napovědět, kde je chyba.
Mysli na to, že v programování záleží na každém znaku. Vše pečlivě zkontroluj!

Řešení

Replit NameError.png

Objeví se chybová hláška podobná této.

Poslední řádek chybové hlášky nás informuje, že Python narazil na nedefinované jméno ObjemKryhle. Kromě toho se dozvíme, že se tohle jméno nachází na čtvrtém řádku zdrojového kódu. Je to divné, objem krychle jsme přece vypočetli už o řádek výš!

Pozornou kontrolou ale zjistíme, že jsme výseldek uložili do proměnné ObjemKrychle, tisknout ale chceme hodnotu proměnné ObjemKryhle. Proměnné s tímto chybným názvem jsem ale přiřadili žádnou hodnotu, takže taková proměnná vůbec neexistuje. Není divu, že si s takovou situací Python poradit neumí. Díky hlášení teď můžeme chybu opravit.

Datový typ proměnné

Viděli jsme, že proměnná má název a hodnotu. Pro úplnost dodejme, že má také datový typ. O tom už jsme se zmínili v kapitole o informaci. Všechna data v počítači jsou sice nuly a jedničky, ale interpretovat je můžeme různým způsobem. Stejný princip je za „typy souborů“ (texty, obrázky, programy…) a za typem buňky v tabulkovém procesoru.

ikona boxu
Úloha: Typ čísla v tabulkovém procesoru
  1. Zadej v tabulkovém procesoru datum 29. října 1969Proč jsme asi pro učebnici informatiky vybrali právě tohle datum?.
  2. Změň typ čísla v buňce na běžné číslo.
  3. Prozkoumej a vysvětli, co se stalo, a co znamená zobrazená hodnota.
  4. Odkdy tvůj tabulkový procesor počítá čas? Jak to nejrychleji zjistit?
  5. Jak tvůj tabulkový procesor počítá s hodinami, minutami a sekundami?
ikona boxu
Nápověda

Po změně typu čísla se v buňce s datumem objevilo nějaké nesmyslné číslo. Stala se nějaká chyba, nebo je to jen jinak zobrazené původní datum? Ověř to změnou formátu čísla zpět na datum.

Číslo je tedy nějakou reprezentací datumu. Zkus na číslo převést několik různých datumů. Jak se liší? Je nějaký vztah mezi rozdílem datumů a rozdílem příslušných čísel?

Řešení

Tabulkové procesory (a s nimi většina ostatních programů) pohlížejí na datumy jako na čísla. Počáteční datum je to, které odpovídá číslu nula. Číslo reprezentuje čas uplynulý od počátku. To zjednodušuje počítání různých časových lhůt. Stačí totiž počítat rozdíly čísel a není třeba hledět na převody roků, měsíců a dnů. Schválně zkus rychle spočítat, kolik uběhlo dnů mezi 23. června 1912 a 7. červnem 1954. Potom spočti rozdíl 19882 - 4558. Co je rychlejší?

Převod na lidsky čitelné datum počítač provede až při nutnosti jej skutečně zobrazit. Vnitřně pracuje nadále s pořadovým číslem dne od počátku.

Scratch datove typy jsou tvary.png

Zkušení programátoři ve Scratchi vědí, že s hodnotami v odlišných tvarech lze provádět odlišné operace a nelze je míchat mezi sebou.

V Pythonu jsme se zatím setkali s celými a s desetinnými čísly. Ta jsou vnitřně reprezentována různým způsobem, takže jde o různé datové typy. Zjednodušeně lze říct, že kladná celá čísla jsou uložena přímočaře ve dvojkové soustavě, jak ji znáš. Drobná komplikace je se zápornými čísly — potřebujeme vyjádřit to „mínus“, jenže pomocí nul a jedniček a tak, aby zápis nebylo možné přečíst prostě jako kladné celé číslo ve dvojkové soustavě. Ještě víc přemýšlení vyžadují čísla desetinná. Je totiž potřeba nějak zaznamenat pozici té desetinné čárky. Protože to vyžaduje odlišnou reprezentace hodnot, jsou celá čísla a tzv. čísla s plovoucíVe významu „pohyblivou“, z anglického floating point. řádovou čárkou odlišným datovým typem.

Další důležité datové typy jsou logické hodnoty (True a False) a textové řetězce (posloupnosti znaků). S odlišnými datovými typy lze provádět odlišné operace (to je další důvod, proč typy rozlišovat). Čísla chceme umět např. sčítat či porovnávat, v textech chceme častěji třeba hledat a nahrazovat slova.

Příklad: Hwair

Podívejme se na následující čtyři bajty a různé způsoby, jak je číst:

data datový typ interpretovaná hodnota
11110000 10010000 10001101 10001000
(hexadecimálněv šestnáctkové soustavě: F0 90 8D 88)
Celé číslo bez znaménka (nezáporné)„Běžná dvojková soustava“ 4 036 005 256
Celé číslo se znaménkemI znaménko je nutno vyjádřit pomocí 0 a 1. Je tedy nutno rozlišit, které bity jsou číslice dvojkového zápisu a které něco jiného, třeba právě znaménko. -258 962 040
Číslo s plovoucí řádovou čárkou(typ float podle normy IEEE754, Single precision 32-bit) -3.57895537573448183054008844288E29,
tedy přibližně -3,58⋅1029 (mínus 358 kvadriliard)
znaky kódované jako ASCII - Latin 2Tedy ASCII doplněné o znaky středoevropských abeced. ­ÉŹł
(První ze čtyř znaků je tzv. rozdělovník, použil by se
při dělení slova na konci řádku. Tady se proto vůbec vůbec nezobrazí.)
znak kódovaný jako UTF-8 Gothic letter hwair.svg (U+10348)
barva kódovaná jako RGBARGBA je obvyklé RGB doplněné o tzv. alfa kanál, tedy průhlednost.  

Tady vidíš, jak mohou stejná data vést ke zcela různým hodnotám.

Postupně se dostaneme i k mnohem složitějším datovým typům a možná si nějaké vlastní taky vytvoříme.

Příklad na závěr

Příklad: Opakovaný výpočet

Náš farmář je trochu popleta. V rozměrech pole zaměnil desítky a jednotky. Správně je to tedy 64, 87 a 68 metrů. Jak teď co nejsnáze zjistit správný obsah pole k osetí? Většinu práce jsme už přece udělali, nechce se nám ji tedy opakovat. Teď se opět projeví výhoda použití proměnných. Náš zápis lze totiž využít znovu a nepotřebuje ani upravovat. Stačí za proměnné a, b a c dosadit opravené hodnoty, a potom už jen z historie vyvolat příkaz na výpočet poloviny obvodu (aby se nepoužila stará hodnota) a následně příkaz na výpočet obsahu. K výpočtu se použijí naposled zadané, tedy změněné hodnoty proměnných, a dostaneme tak odpovídající nový výsledek. Zkus to!

Řešení

import math
a = 64
b = 87
c = 68
PulObvodu = (a+b+c)/2
Obsah = math.sqrt(PulObvodu * (PulObvodu - a) * (PulObvodu - b) * (PulObvodu - c))

Řádky se samotným výpočtem neobsahují žádné konkrétní číselné hodnoty, jen promměné. Lze je proto použít v nezměněné podobě, přímo z historie příkazů.

Můžeš také zkusit nějaké známé trojúhelníky, třeba se stranami 3, 4 a 5, nebo 1, 1 a math.sqrt(2), aby bylo možno výsledek snadno ověřit.

Jak opakované rutinní výpočty provádět ještě efektivněji zjistíš v následující kapitole.

Shrnutí

ikona boxu
  • Proměnné nám umožňují pracovat s hodnotami prostřednictvím jejich pojmenování. Díky tomu si konkrétní hodnoty netřeba pamatovat a stejné postupy lze opakovat pro různé hodnoty.
  • Proměnnou vytvoříme (nebo změníme její hodnotu) přiřazením hodnoty výstižnému jménu, např.: DenVMesici = 23.
  • Proměnnou použijeme kdekoliv, kde bychom jinak museli vypisovat její hodnotu, např.: ZbytekDnuVMesici = PocetDnuVMesici - DenVMesici .
  • Datový typ proměnné určuje, co lze s proměnnou provádět (počítat, logicky odvozovat, spojovat...).

Úlohy k procvičení

Cvičit můžeš s jakýmikoliv výpočty, dost složitými, aby se vyplatilo uložit mezivýsledky a další hodnoty do proměnných. Až budeš příště něco počítat, vzpomeň si na Python.

ikona boxu
Trable s desetinnými čísly

Jeden z důvodů, proč musí programátoři sledovat, jestli pracují s celými nebo necelými čísly, je přesnost. U celých čísel není problém. U ostatních je ovšem třeba počítat se zaokrouhlováním. Podívej se na následující výpočet a tipni si, jaký by měl být výsledek:

10*0.1 - (0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1)

Připadne ti, že mezi desetinásobkem jedné desetiny a součtem deseti desetin není rozdíl, takže by měla vyjít nula? Vlož kód do konzole, uvidíš, co řekne... Cože?!

Zjisti a vysvětli, v čem je potíž. Nápověda: má to co dělat s tím, jak jsou čísla uložena v počítači (takže se asi vyplatí podívat na výpočet jeho očima).