Ujukoma

Sisesta kümnendarv. Allpool näed teisenduskäiku täpselt nii, nagu arvutaksid seda paberil. Ülemine rida näitab aga tulemust, mis lõpuks arvuti mällu jääb.

Interaktiivse simulatsiooni laadimine...
Õppetund

Teooria — Ujukoma248 sõna

Ujukomaarv on kahe astmega korrutatud täisarv: (−1)s × 1.f × 2E−1023. Vorming määrab, mitu bitti läheb tähisele E ja mitu tähisele f. See üksik jaotus paneb paika, kui kaugele vormingu ulatus küündib ja kui täpselt see kahte arvu suudab eristada.

Mida iga sümbol tähendab

s
märgibitt, 0 tähistab positiivset ja 1 negatiivset. See asub eraldi ega ole arvuga kokku sulandatud. Seetõttu on vormingus olemas nii +0 kui ka −0.
E
astendaja väli. Arvuti hoiab seda nii, et sellele on liidetud 1023. Nii saab väärtus minna negatiivseks, ilma et vajaks eraldi märgibitti. See väli valib arvupiirkonna. Piirkond aga määrab, kui kaugel naabrid teineteisest asuvad.
f
murdosa: 52 bitti, mis järgnevad juhtivale arvule 1. Seda esimest ühte mälus ei hoita, sest normaliseeritud arv algab nagunii alati ühega. Need 52 bitti annavad kogu arvu täpsuse. Astendaja ise ei lisa täpsusele mitte midagi.
Eeldab
Et tegu on lõpliku normaalarvuga. Väärtusest 2−1022 allpool jäetakse juhtiv 1 ära. Vorming töötab küll edasi, kuid ohverdab selleks täpsust. Vähim positiivne topelttäpsusega arv on seega 4,94 × 10−324, mis kannab endas vaid ühtainsat mantissi bitti.
Ei kehti, kui
Kahes kohas. Mõlemad olukorrad tulevad ette päris koodis. Arvutatud väärtuste võrdlemine operaatoriga = ebaõnnestub alati, kui tulemusteni jõuti eri teid pidi. Erinevad lahenduskäigud lihtsalt ümardavad erinevalt. Pika summa puhul mängib aga rolli liitmise järjekord. Liida jada liikmed kokku algusest lõpuni ja seejärel vastupidi ning lõppsummad tulevad erinevad. Kõige vähem läheb täpsust kaduma siis, kui alustad liitmist kõige väiksematest liikmetest.

Kaheksa tuhandest 🖖

Arvude 0,001 ja 1,000 vahel on ainult kaheksa väärtust, mis salvestuvad täiesti veatult. Need on 0,125, 0,25, 0,375, 0,5, 0,625, 0,75, 0,875 ning 1. Kahendmurd koosneb alati pooltest, veeranditest, kaheksandikest ja nii edasi. Nimetaja 1000 sisaldab aga tegurit 125, mida ükski kahe aste ei suuda eemaldada. Sisesta 0,375 ja rakendus loeb selle täpseks. Arvu 0,376 puhul see enam nii ei ole.

0,1 + 0,2 satub täpselt keskele 🖖

Kahe salvestatud väärtuse summa on 0,3000000000000000166533453693773481063544750213623046875. See on täpne keskpunkt arvust 0,3 kummalgi pool asuva kahe topelttäpsusega arvu vahel. Liitmistehe ise on laitmatu. Viik tuleb kuidagi murda ja reegel käsib valida naabri, mille viimane bitt on paaris. Arvust 0,3 väiksema arvu murdosa lõpeb paaritu bitiga. Suurem aga paarisbitiga, seega liigub summa ülespoole. Just sealt pärinebki väärtuse 0,30000000000000004 saba.

Vähem bitte, õige vastus 🖖

Vali samade arvudega binary32 vorming. Tehte 0,1 + 0,2 vastuseks tuleb 0,300000011920928955078125. Selles vormingus salvestubki 0,3 just täpselt nii. See kurikuulus viga eeldab, et summa satuks viigiseisu. Ent 24 bitises vormingus jääb summast veerand lünka puudu. Seega ümardub tulemus tagasi sinu oodatud arvuni. Täpsust on poole vähem, aga saad soovitud vastuse.

Vahe kahekordistub iga kahe astmega 🖖

Kogu vahemikus 0,0625 kuni 0,125 on kaugus ühest esitatavast arvust järgmiseni 1,39 × 10⁻¹⁷. Selles vahemikus see suurus ei muutu. Järgmisse vahemikku minnes see kahekordistub. Graafikul olev trepp kujutabki täpselt seda. Iga kahe aste lisab ühe astme. Seetõttu suudabki sama vorming hoida arve 10⁻³⁰⁰ ja 10³⁰⁰, aga ei suuda säilitada väärtust 9007199254740993.

Ülesanne täielikult lahendatud

  1. Maksesüsteem hoiab rahasummasid naeltes ja kasutab selleks binary64 vormingut. Näita, et £0,10 ja £0,20 on mõlemad salvestatud veidi suuremana. Näita, et nende liitmine ei anna kokku £0,30, ja ütle, mida maksesüsteemide insener selle vältimiseks teeb.

    1. Arv 0,1 on kahendsüsteemis 0,0001, millele järgneb igavesti korduv 1001. Kümnendiku nimetajas peab olema viis. Kahendmurrul on aga pakkuda ainult kahtesid ja seepärast ei lõpe see jada kunagi.

    2. Alles hoitakse 53 kahendkohta ja ülejäänu ümardatakse ära. Siin ümarduvad need ülespoole. Seega on salvestatud väärtus arvust 0,1 täpselt 5,55 × 10⁻¹⁸ võrra suurem. Lehel olev ümardamise samm näitab seda suunda noolega.

    3. Arvu 0,2 puhul on kasutusel samad 53 kahendkohta, kuid astendaja on ühe võrra suurem. Seetõttu on ka selle viga täpselt kahekordne ehk 1,11 × 10⁻¹⁷. Sisesta kasti 0,2 ja võrdle neid kahte veakaarti.

    4. Kokku liites satuvad need kaks salvestatud väärtust täpselt 0,3 mõlemal küljel asuva arvu keskpunkti. Viigi korral võidab see naaber, mis lõpeb paarisbitiga. Siinkohal on selleks ülemine naaber.

    5. Niisiis tuleb vastuseks hoopis 0,3000000000000000444089209850062616169452667236328125. Iga järgnev arvutus veab seda viga endaga kaasas.

    6. Sisesta nüüd 0,1 ja 0,2 asemel 10 ning 20. Mõlemad on täisarvud ja jäävad tublisti alla 2⁵³. Mõlemat hoitakse mälus täpselt. 10 + 20 on 30 ja kuskil ei lähe midagi kaduma.

    Vastus

    Hoia rahasummasid väikseima ühiku täisarvuna. Eelista naeltele pensse. Siis on aritmeetika täpne, sest iga täisarv kuni 2⁵³ on veatu. Ainus ümardamine on nüüd see, mille sa ise koodi kirjutad. See juhtub täpselt sinu valitud hetkel ja sa saad sellele alati näpuga osutada. Rakendus suudab mõlemat poolt kümne sekundiga näidata. Sisesta 0,1 ja veakaart pole null. Sisesta 10 ja null ongi seal.

Näiteülesanded

  • 0,1 - Masin salvestab 0,1 kujul 0,1000000000000000055511151231257827021181583404541015625. Arvu 0,2 puhul on viga täpselt kaks korda suurem. Nende kahe summa satub täpselt 0,3 mõlemal poolel asuva arvu keskele. Viigimurdmise reegel määrab siin suuna ja summa ümardatakse ülespoole.
  • 0,375 - Kahendsüsteemi rida katkeb pärast kolme kohta ega jookse lõputult edasi. Rakendus nimetab seda väärtust täpseks. Arv 0,375 vastab murrule 3/8 ja kahendmurrud just kaheksandikest koosnevadki. Muuda viimane number väärtuseks 0,376 ning jada ei lõpe enam kunagi.
  • 0,1 32 bitis - Sama 0,1 juhul, kui mantiss on 53 biti asemel 24-bitine: seda hoitakse kujul 0,100000001490116119384765625 ja tööriist näitab 7,22 kümnendkohta. Liida siia 0,2 ning vastuseks saad 0,300000011920928955078125. Just täpselt nii salvestub selles vormingus arv 0,3.
  • 2⁵³ + 1 - Väärtusest 2⁵³ alates kasvab arvude vahe suuruseni 2 ja iga teine täisarv on puudu. 9007199254740993 asub täpselt kahe võimaliku arvu vahel. Viigimurdmine langetab selle alla väärtuseni 9007199254740992, tekitades vea −1. Samal põhjusel ei anna siin arvu 1 liitmine mingit efekti.
  • 10¹⁶ + 1 - Nii 10¹⁶ kui ka 1 salvestuvad veatult. Nende liitmine 10¹⁶ + 1 annab aga vastuseks ikkagi 10¹⁶. Naabrite vahe on siin 2. Arv 10000000000000001 on seega kahe naabri vahel viigis. Sama paarisarvulise viimase biti reegel, mis lükkas tehte 0,1 + 0,2 ülespoole, tõmbab selle arvu siin tagasi alla.