Zřejmě každý začínající programátor na tento problém narazí, když hledá v chybu ve zdánlivě správné konstrukci.
Například tento jednoduše vypadající cyklus je nekonečný:
a = 0;
|
Kdo se s tím ještě nesetkal, tak asi řekne "Sakra jak to? Desetkrát se k nule přičte 0,1 a musí to skončit." A ono ne.
Pamět umí uchovat pouze 2 stavy (dvojková soustava), ale člověk používá desítkovou soustavu. Čísla se tedy musejí mezi soustavami převádět.
Postup: Číslo v desítkové soustavě dělíme celočíselně dvojkou, zbytky po dělení píšeme postupně před sebe až do doby, kdy nám po celočíselném dělení zůstane nula.
11 | / | 2 | = | 5 | (zbytek 1) |
5 | / | 2 | = | 2 | (zbytek 1) |
2 | / | 2 | = | 1 | (zbytek 0) |
1 | / | 2 | = | 0 | (zbytek 1) |
Při celočíselném počítání problém nenastává. Každé číslo se dá zapsat v konečném tvaru, v nejhorším je moc velké a program ohlásí chybu.
Postup: Celá část se převádí stejným způsobem jako celá čísla. Desetinná část se převádí tak, že ji postupně násobíme dvojkou, zapisujeme za sebe celou část a dál počítáme opět pouze s desetinnou, dokud nám nezůstane nula.
0,6875 | * | 2 | = | 1,375 | (celá část 1) |
0,375 | * | 2 | = | 0,75 | (celá část 0) |
0,75 | * | 2 | = | 1,5 | (celá část 1) |
0,5 | * | 2 | = | 1,0 | (celá část 1) |
Převod reálný čísel vypadá taky bezproblémově.
Když si představíme graficky převod reálných čísel, tak se dostaneme k půlení intervalu. Desetinná část leží v intervalu od jedné do nuly, rozdělíme si tento interval na dvě poloviny (tzn. 0 - 0,5 a 0,5 - 1). Pokud je číslo v první polovině, tak si zapíšeme nulu, pokud v druhé tak jedničku. Takto můžeme pokračovat až do doby, než narazíme přesně na převáděné číslo (navigace po číselné ose). Toto hledání může být ale velmi dlouhé, někdy i nekonečné. Paměť počítače není nekonečná, takže tu "nepodstatnou" malou část na konci zahodíme.
A tady nastává problém. Uložené číslo není přesné a proto nám rovnost v úvodním cyklu nikdy neskončí. Řešením je nepoužívat rovnost, ale operátory větší než a menší než. V úvodním cyklu stačí změnit podmínku na "a >= 1".
Pro zjednodušení budeme mít 8 místné kladné celé decimální číslo, kde prvních 6 míst budou platná číslice a 2 místa bude mantisa.
1 | 2 | 3 | 4 | 5 | 6 | 1 | 2 |
1e1 | = | 10 |
2e2 | = | 200 |
1e6 | = | 1 000 000 |
1e9 | = | 1 000 000 000 |
Z příkladů je vidět, že takhle můžeme jednoduše uložit dosti rozdílné hodnoty. Problém nastane u čísel, která mají více platných číslic. Např. číslo 123456789 ma 9 platných číslic, ale můžeme uložit pouze prvních 6, další číslice tedy zahodíme a uložené číslo bude 123456e2. Ve většině případů nám toto zaokrouhlení nevadí.
Co se ale stane, když k předchozímu číslu přičteme 1? Dostaneme číslo 12345601 a po uložení opět 123456e2. Když si pod tím představíme peníze - co to je 1 koruna při více než 12 miliónech? Nic, ale co když toto přičtení koruny provedeme miliónkrát? Najednou přijdeme o milión korun a to už taková sranda není, že? A stačilo by těch milión korun nejprve sečíst a až potom je přičítat.
V jazyku C jsou 3 typy reálných čísel. Do typu float se uloží 7 platných číslic, do typu double 15 a do long double 19 číslic. Použití přesnějšího čísla problém pouze odsune, ale nevyloučí chybu při nesprávném použití.
Zde si můžete vyzkoušet převody číselných soustav. K funkci je potřeba zapnutý javascript. Hodnota chyba zaokrouhlení nemusí být přesná.
Soustava | Cislo | |
Prevod z | ||
Prevod do | ||
Dalsi informace | ||
Chyba zaokrouhleni (v desitkove): |