mi a legkisebb 0-nál nagyobb szám? Ez egyike azoknak az egyszerű kérdéseknek, amelyek bonyolult válaszokat tartalmaznak valahol a “Nincs” és a “attól függ”között.
ha megkérdezel egy matematikust, azt fogják mondani, hogy nem lehet ilyen szám, mert megtörné a matematikát. Ha van n számod, ahol n A legkisebb szám 0 után, akkor nem lehet N/2 szám, mert n már a legkisebb. Ez azt jelenti, hogy maga a felosztás lebomlik, ami a matematikusoknak nem tetszik.
ha megkérdez egy számítógépet, akkor valóban választ kap. A való világgal ellentétben a számítógépek nem rendelkeznek végtelen számú számmal, mert egyszerűen nem férnek el. A számítógépek a memóriaregiszterekben tárolják a számokat, és minden regiszter rögzített számú bittel rendelkezik. Képzelje el, ha csak három számjegye lenne. A legnagyobb szám, amelyet képviselhet, a 999 lenne. Ez történik egy számítógépen.
ez azt jelenti, hogy a számítógép egész számkészletét a számjegyek száma korlátozza. Egy számítógépben határozottan van egy legnagyobb szám (például INT_MAX
a C-ben). Ez a szám a számjegyek maximális mennyiségével, amelyek mindegyike bináris 1
. Egy 8 bites rendszeren ez a szám 11111111
lenne.
még tovább bonyolíthatjuk a dolgokat, ha negatív számokat is belefoglalunk. Ha 8 Bit adatunk van, akkor az első bitet használhatjuk a szám jelének ábrázolására. 0
plusz és 1
mínusz esetén. Most 7 bitünk van a számjegyeinkhez, tehát a legnagyobb szám 011111111
, amely kisebb, mint az előző legnagyobb számunk.
még mindig nem végeztünk. Decimális számokat is kell képviselnünk. Még ha a 0,12 is kis szám, akkor is három számjegye van, akárcsak a 123. A különbség az, hogy van még egy dolog, amire gondolnunk kell: a decimális pont, más néven radix pont. Meg kell tárolnunk mind a számjegyeket, mind a radix pont helyzetét.
míg az egész számok korlátozottak abban, hogy milyen nagyok lehetnek, a decimális számok mind méretükben, mind pontosságukban korlátozottak. Ha rögzített számjegy van, akkor csak annyi számjegy van, amelyet a tizedes pont után helyezhet el. Ez az oka annak, hogy a számítógépeknek tizedes számokat kell kerekíteniük.
hogyan tároljuk ezeket a tizedes számokat? A számítógépek csak egész számokat értenek, ezért szükségünk van egy decimális szám tárolására csak egész számok használatával.
mondjuk, hogy megvan a 3.14
szám. Kezdjük azzal, hogy megírjuk a szám összes számjegyét. Kapunk 314
. Kezdetnek nem rossz. Tudjuk, hogy a 10-es hatványokkal megszorozva “mozgathatjuk” a tizedespontot a szám körül. A 314 * 10^-1
31,4, míg a 314 * 10^-2
3,14.
a 3.14 számhoz mindössze három egész számra van szükségünk: 314, 10 és -2. A 314 az, amit jelentésnek nevezünk, és ez a szám összes számjegye.A
10-et radixnek vagy bázisnak nevezzük. Tudjuk, hogy a 10-es hatványokkal való szorzással a tizedes pontot a 10-es bázisban lévő számok körül mozgathatjuk. Ugyanez működik az összes számbázis esetében: a 2.bázisban (vagy bináris) a pontot 2-es hatványokkal szorozva eltolhatja.
az eltolódó erőt kitevőnek nevezzük, és megmutatja, hol van a tizedes pont.
minden tizedes számot e három számként írhat egy egyszerű képlettel:
number = significand * base^exponent3.14 = 314 * 10^-2
32.8 = 328 * 10^-1
a számítógép decimális számot tárol úgy, hogy a jelet, a kitevőt és a jelentést egyetlen, 32 vagy 64 bites számjegyből álló karakterláncban tárolja. Általában 1 bit van a jel számára, 11 bit a kitevő tárolására, 53 bit pedig a jelentés tárolására, összeadva 64-et.
ezt szem előtt tartva térjünk vissza a kérdésünkre: Mi a legkisebb nem nulla szám? Ha csak három számjegyünk van, akkor a lehető legkisebb szám 0,01. Négy számjeggyel 0,001. Itt észrevesz egy mintát: a jelentés mindig ugyanaz, csak a kitevő változik.
amire szükségünk van, az a 1
jelentése, mert ez a legkisebb a 0
után. Ezután a tizedesvesszőt balra kell tolnunk, amennyire csak tudunk. Ehhez szükségünk van a legkisebb (leginkább negatív) lehetséges exponensre.
milyen kicsi, a memóriában lévő szám elrendezésétől függ. Ha 11 bitünk van az exponens számára, akkor csak egy 10 bit hosszú számot írhatunk ki, 1 bitet fenntartva a jel számára. Egy 64 bites rendszerben a legkisebb kitevő -308
.
végül a lehető legkisebb szám egy 64 bites rendszerben 1 * 10^-308
körül lenne. Ez kicsi!
megállapítottuk, hogy van egy legkisebb szám. Ez a szám megmutatja, mennyire bízhatunk a számítógépünkben. Ha olyan dolgot csinál, amely nagyon nagy számokat vagy nagyon pontos számokat igényel, akkor ezt a számot szem előtt kell tartania.
amit most kiszámoltunk, az az utolsó helyen lévő egység, vagy ulp, 0. Eltekintve attól, hogy nagyon klassz szó, az ulp elmondja nekünk, hogy mekkora a minimális távolság a számítógép két száma között. Kiszámítottuk a 0 ulp-jét, amely a 0 és a következő szám közötti minimális távolság.
ha hozzáadja a számított értéket 0-hoz, és megpróbálja összehasonlítani őket, akkor nem ugyanaz a szám. Ha azonban az ulp-nél kisebb értéket ad hozzá, akkor az továbbra is ugyanaz a szám, ami a számítógépet illeti.
print(0 == 0 + ulp(0)) // false
print(0 == 0 + ulp(0) / 2) // true
számunkra nyilvánvaló, hogy egy nem nulla érték hozzáadása egy számhoz más számot eredményez, de a számítógépnek valahol kerekítenie kell, így nem feltétlenül tudja megmondani, hogy két szám azonos-e.
a számítógépes rendszerek könnyebb összehasonlításához az 1 ulp-jét használjuk, és ezt a gépet epsilonnak nevezzük. Miután megismerte a gépet epsilon, bármilyen más ulp-t kiszámíthat a következő képlettel:
ulp(x) = machine epsilon * radix^exponent(x)
a kiszámított érték nagyon kicsi, így valószínűleg nem fogja elérni ezt a határt kódolás közben. De, kiszámítottuk a 0 értékét. Ha több számjegy szükséges a tizedes pont bal oldalához, annál kevesebb van a jobb oldalon. Ez azt jelenti, hogy minél nagyobb a szám, annál kevésbé pontos. Más szavakkal, az ulp az exponens közvetlen függvénye. Ahogy jobbra tolja a tizedes pontot, az ulp növekszik, és elveszíti a pontosságot.
remélem, hogy ez az információ segít legközelebb, amikor furcsa lebegőpontos hibát kap a kódjában. Ne feledje, hogy a számítógépek elég erősek, de még a számítógépnek is vannak korlátai.