Jaké je nejmenší číslo větší než 0? Toto je jedna z těch jednoduchých otázek se složitými odpověďmi někde mezi „neexistuje“ a „záleží“.
pokud se zeptáte matematika, řeknou vám, že takové číslo nemůže být, protože by to rozbilo matematiku. Pokud máte číslo n, kde n je nejmenší číslo po 0, pak nemůže být číslo n / 2, protože n je již nejmenší. To znamená, že samotné dělení se rozpadá, což se matematikům nelíbí.
pokud se zeptáte počítače, dostanete odpověď. Na rozdíl od skutečného světa nemají počítače nekonečné množství čísel, protože se prostě nevejdou. Počítače ukládají čísla do paměťových registrů a každý registr má pevný počet bitů. Představte si, že máte jen tři číslice. Největší číslo, které byste mohli reprezentovat, by bylo 999. To se děje v počítači.
to znamená, že sada celých čísel v počítači je omezena počtem číslic. V počítači je určitě největší číslo (například INT_MAX
v C). Je to číslo s maximálním počtem číslic, z nichž všechny jsou nastaveny na binární 1
. V 8bitovém systému by toto číslo bylo 11111111
.
můžeme situaci ještě více komplikovat zahrnutím záporných čísel. Pokud máme 8 bitů dat, můžeme použít první bit k reprezentaci znaménka čísla. 0
Pro plus a 1
pro mínus. Nyní máme 7 bitů pro naše číslice, takže největší číslo je 011111111
, což je menší než naše předchozí největší číslo.
ještě jsme neskončili. Musíme také reprezentovat desetinná čísla. I když 0,12 je malé číslo, stále má tři číslice, stejně jako 123. Rozdíl je v tom, že je tu ještě jedna věc, o které musíme přemýšlet: desetinná tečka, také nazývaná radix bod. Musíme uložit jak číslice, tak polohu bodu radix.
zatímco celá čísla jsou omezena v tom, jak velká mohou být, desetinná čísla jsou omezena jak velikostí, tak přesností. Pokud máte pevný počet číslic, je tu jen tolik číslic, které můžete dát za desetinnou tečku. To je důvod, proč počítače potřebují zaokrouhlit desetinná čísla.
Jak tedy uložíme tato desetinná čísla? Počítače chápou pouze celá čísla, takže potřebujeme způsob, jak uložit desetinné číslo pouze pomocí celých čísel.
Řekněme, že máme číslo 3.14
. Začněme tím, že napíšeme všechny číslice čísla. Dostaneme 314
. To je začátek. Víme, že vynásobením mocninami 10 můžeme“ přesunout “ desetinnou čárku kolem čísla. 314 * 10^-1
je 31,4, zatímco 314 * 10^-2
je 3,14.
vše, co potřebujeme k reprezentaci čísla 3.14, jsou tři celá čísla: 314, 10 a -2. 314 je to, co se nazývá significand, a toto jsou všechny číslice odepsaného čísla.
10 se nazývá radix nebo báze. Víme, že vynásobením mocninami 10 můžeme pohybovat desetinnou tečkou kolem čísel v základu 10. Totéž platí pro všechny číselné základny: v základně 2 (nebo binární) můžete tečku posunout vynásobením mocninami 2.
síla, kterou posuneme, se nazývá exponent a říká nám, kde je desetinná tečka.
můžete psát každý desetinné číslo jako ty tři čísla s jednoduchý vzorec:
number = significand * base^exponent3.14 = 314 * 10^-2
32.8 = 328 * 10^-1
počítač ukládá desetinná čísla uložením znaménko, exponent a significand v jeden řetězec 32 nebo 64 bit číslic. Obvykle existuje 1 bit pro znak, 11 bitů pro uložení exponentu a 53 bitů pro uložení významu, sčítající až 64.
s ohledem na to se vraťme k naší otázce: Jaké je nejmenší nenulové číslo? Pokud máme k dispozici pouze tři číslice, nejmenší možné číslo je 0,01. Se čtyřmi číslicemi je to 0,001. Zde si všimnete vzoru: význam je vždy stejný, mění se pouze exponent.
potřebujeme význam 1
, protože to je nejmenší po 0
. Pak musíme posunout desetinnou čárku co nejdále doleva. K tomu potřebujeme nejmenší (nejvíce negativní) možný exponent.
jak malé, závisí na rozložení čísla v paměti. Pokud máme 11 bitů pro exponent, můžeme jen napsat číslo, které je 10 bitů, 1 bit rezervován pro znaménko. V 64bitovém systému je nejmenší exponent -308
.
nakonec by nejmenší možné číslo v 64bitovém systému bylo kolem 1 * 10^-308
. To je malý!
zjistili jsme, že existuje nejmenší číslo. Toto číslo nám říká, jak moc můžeme důvěřovat našemu počítači. Pokud děláte něco, co vyžaduje velmi velká čísla nebo velmi přesná čísla, musíte mít toto číslo na paměti.
to, co jsme právě vypočítali, je něco, co se nazývá jednotka na posledním místě, nebo ulp, z 0. Kromě toho, že je to opravdu skvělé slovo, ulp nám říká, jaká je minimální vzdálenost mezi dvěma čísly v počítači. Vypočítali jsme ulp 0, což je minimální vzdálenost mezi 0 a dalším číslem.
pokud přidáte vypočtenou hodnotu na 0 a pokusíte se je porovnat, nebude to stejné číslo. Pokud však přidáte hodnotu menší než ulp, bude to stále stejné číslo, pokud jde o počítač.
print(0 == 0 + ulp(0)) // false
print(0 == 0 + ulp(0) / 2) // true
Pro nás je zřejmé, že přidání nenulovou hodnotu na číslo, bude produkovat jiné číslo, ale počítač má někde kolem, takže to není nutně říct, jestli dvě čísla jsou stejná.
pro snadnější porovnání počítačových systémů používáme ulp 1 a nazýváme jej stroj epsilon. Jakmile znáte stroj epsilon, můžete vypočítat jakýkoli jiný ulp pomocí následujícího vzorce:
ulp(x) = machine epsilon * radix^exponent(x)
hodnota, kterou jsme vypočítali, je velmi malá, takže při kódování pravděpodobně tento limit nedosáhnete. Ale vypočítali jsme hodnotu pro 0. S více číslic potřebných pro levou stranu desetinné tečky, tím méně máme pro pravou stranu. To znamená, že čím větší číslo, tím menší přesnost máte. Jinými slovy, ulp je přímá funkce exponentu. Když posunete desetinnou tečku doprava, ulp se zvětší a ztratíte přesnost.
doufám, že tato informace vám pomůže se příště budete mít divný plovoucí desetinnou čárkou chyby v kódu. Pamatujte, že počítače jsou docela výkonné, ale i počítač má své limity.