Kuidas sa eristad ASCII erinevust kahend- ja sama koma vahel kahendsüsteemis?


Vastus 1:

Üldiselt ei saa, mitte ainult bittide kaupa. Näiteks arv 00111001 binaarses vormis: see võib olla number 57, kuid see võib olla ka ASCII-number “9”.

Sellegipoolest võite praktikas sageli erinevuse öelda. Sest teil on mingi idee, mis väärtus peaks olema sellel, millega te töötate. Mõelge järgmisele C-funktsioonile, millel on silmatorkav viga:

int print (int n) {char buf [1]; int i; i = 3 * n + 2; sprintf (buf, "% i \ n", i); paneb (buf); tagasta i; }

See arvutab iga täisarvu n jaoks väärtuse 3 * n + 2, eraldab selle väärtuse konsoolile ja tagastab selle täisarvuna. Selle funktsiooni testimisel võite siiski märgata, et kui sisend on näiteks 9, prindib see konsooli õige tulemuse 29. Kuid see tagastab vale väärtuse, antud juhul väärtuse 57. Ja see võib teile siin toimuva kohta pisut aimugi anda, sest märkad, et 57 on number 9 ASCII esitus ja see juhtub nii olema tulemuse viimane number.

Seejärel teete mõned katsed ja leiate, et see on tõsi, kui tulemus on kahekohaline. Näiteks kui n = 5, peaks tulemus olema 17, kuid selle asemel on tulemus 55, ASCII esitus numbril „7“.

Ja kui tulemus koosneb rohkem kui 2 numbrist, on tulemus veelgi nõrgem. Näiteks kui n = 50, siis saadakse õige tulemus 152 konsoolile, kuid tagastamise väärtus on kümnendkoha täpsusega 12853 või kuueteistkümnendsüsteemis 0x3235. Võite märgata, et see on stringi “25” ASCII esitus või tulemuse kaks viimast numbrit vastupidises järjekorras!

Mis siin toimub? Pange tähele, et märkide puhverlaual on ruumi ainult ühele tähemärgile! Funktsioon sprintf () C-s ei kontrolli puhvri ületusi, seega kirjutab ta väljundi õnnelikult mälule, millele buf osutab, kirjutades baiti kohe ümber bufile reserveeritud baitidele, kui buf on liiga väike. Sel juhul on need täisarv i jaoks reserveeritud baitid ja need kirjutatakse üle. Ja kuna i funktsiooni kasutatakse siis selle funktsiooni tagastamisväärtusena, on tagastamise väärtus vale.

Jääb ainult üks küsimus: miks tagasiväärtus sisaldab tulemuse viimaseid ASCII numbreid, kuid vastupidises järjekorras? See juhtub seetõttu, et (eeldusel, et töötate arvutiga), täisarvu baite salvestatakse "valesti". Näiteks 32-bitine täisarv 0x12345678 salvestatakse mällu baitidena 0x78 0x56 0x34 0x12.

Niisiis, kui sisend on n = 50, salvestatakse tulemuse esimene number buf-vormingus, tulemuse teine ​​ja kolmas number lõppevad i-ga, mis seejärel muutub baitides 0x35 0x32 0x00 0x00. Ja see tähistab väärtust 0x3235 = 12853 kümnendarvuna, kui seda tõlgendatakse 32-bitise arvuna.

Viimane märkus: kui prooviksite seda tegelikult oma arvutis, võivad tulemused olla erinevad, kuna seda tüüpi vea mõju sõltub suuresti teie masina ja kompilaatori sisemisest tööst. Nt salvestab nutitelefon enamasti oma baitid õiges järjekorras, nii et saate selle tulemusel erineva numbri. Ja teie kompilaator võib mälu joondamise probleemide tõttu reserveerida rohkem kui 1 baiti buf-i jaoks, või võib see salvestada bufi ja i vastupidi (ma esmalt mällu, siis buf). Või võib see optimeerida i, hoides tulemust ainult protsessori registris. Sel juhul on tulemus õige, kuid midagi muud mälus rikutakse.

Üldiselt, kui programmid sisaldavad selliseid vigu, on kõik ennustused selle kohta, mis tegelikult juhtub.


Vastus 2:

Kui 48 on arvu nulli ASCII esitus ja 57 on üheksa ASCII esitus, siis on väikseim nibeldus tegelik arv:

0000 0000-0011 0000 = 32 + 16 + 0 = 48

0000 0001-0011 0001

0000 0010-0011 0010

0000 0011-0011 0011

0000 0100-0011 0100

0000 0101-0011 0101

0000 0110-0011 0110

0000 0111-0011 0111

0000 1000-0011 1000

0000 1001-0011 1001 = 32 + 16 + 8 + 1 = 57

või lihtsalt; lahuta 48, et sulle number anda.