ASCII-in ikili və eyni ikili ikincidə olan fərqi necə deyə bilərsiniz?


cavab 1:

Ümumiyyətlə, yalnız bitlərdən keçə bilməzsiniz. Məsələn, ikili formada 00111001 nömrəsi: 57 nömrəsi ola bilər, eyni zamanda ASCII "9" nömrəsi də ola bilər.

Praktikada, fərqi tez-tez görə bilərsiniz. Çünki hansı dəyərlə işləmək lazım olduğuna dair bir fikriniz var. Aşkar bir səhv olan aşağıdakı C funksiyasını nəzərdən keçirək:

int print (int n) {char buf [1]; int i; i = 3 * n + 2; sprintf (buf, "% i \ n", i); dəstlər (buf); qayıt i; }}

Hər bir n üçün 3 * n + 2 dəyərini hesablayır, bu dəyəri konsola verir və dəyəri tam olaraq qaytarır. Bununla birlikdə, bu xüsusiyyəti sınaqdan keçirərkən, 9-u daxil etsəniz, məsələn, 29-un düzgün nəticəsi konsolda çap ediləcəyini öyrənə bilərsiniz. Ancaq səhv olan dəyər geri qaytarılır, bu vəziyyətdə 57 dəyər. Və bu, burada baş verənlərə dair bir məlumat verə bilər, çünki 57 nömrənin 9 nömrəli ASCII nümayəndəliyi olduğunu və bu son rəqəm olacağını tapacaqsınız nəticənin.

Sonra təcrübə aparırsınız və nəticə iki rəqəmli bir nömrə olduqda bunun doğru olduğunu tapırsınız. Məsələn, n = 5 ilə nəticə 17 olmalıdır, əksinə nəticə 55, "7" rəqəminin ASCII təmsilidir.

Nəticədə 2-dən çox rəqəm varsa, nəticə hətta qəribədir. Məsələn, n = 50 ilə düzgün nəticə 152 konsolda çıxır, ancaq geri qaytarılma dəyəri onluğa 12853 və ya hexadecimal sayıda 0x3235-dir. Bunun "25" sətrinin ASCII nümayəndəliyi olduğunu və ya nəticənin son iki rəqəminin tərs qaydada olduğunu bilər.

Bəs burada nə baş verir? Xarakter tamponu yalnız bir simvol üçün yer təklif etdiyini unutmayın! C-dəki sprintf () funksiyası tampon daşımalarını yoxlamır, buna görə çıxışı bufla göstərilən yaddaşa yazmağı sevir və buf çox kiçik olduqda buf üçün ayrılmış baytlardan dərhal sonra baytların üstünə yazır. Bu vəziyyətdə, bunlar tam ədəd üçün ayrılmış baytlardır və onlar yenidən yazılır. Bundan sonra i dəyəri bu funksiyanın qayıdış dəyəri kimi istifadə edildiyi üçün qayıtma dəyəri səhvdir.

Yalnız bir sual qalır: niyə geri dönüş dəyəri nəticənin son ASCII rəqəmlərini ehtiva edir, əksinə? Bunun səbəbi (bir PC-də işlədiyinizi güman etdiyiniz zaman) tam ədədin baytlarının "yanlış yol yuvarlaqlığı" altında saxlanmasıdır. Məsələn, 32 bitlik 0x12345678 yaddaş yaddaşda bayt 0x78 0x56 0x34 0x12 şəklində saxlanılır.

Giriş n = 50 olarsa, nəticənin ilk rəqəmi bufda, nəticənin ikinci və üçüncü rəqəmləri i ilə bitərsə, sonra bayt 0x35 0x32 0x00 0x00 olur. Və bu 32 bitlik bir nömrə kimi təfsir edilsə 0x3235 = 12853 dəyərini onluğa ifadə edir.

Son bir qeyd olaraq, həqiqətən bunu kompüterinizdə sınamısınızsa, nəticələr fərqli ola bilər, çünki bu tip səhvlərin təsiri kompüterinizin və kompilyatorunuzun içindən çox asılıdır. Məsələn, bir smartfon adətən baytlarını düzgün qaydada saxlayır ki, fərqli bir nömrə əldə edəsiniz. Və kompilyator yaddaşın uyğunlaşdırılması problemi səbəbindən buf üçün 1 baytdan çox ehtiyat ayıra bilər və ya bufı saxlaya bilər və əksinə (əvvəlcə yaddaşda, sonra bufda). Və ya nəticəni yalnız bir CPU qeydində saxlayaraq optimallaşdıra bilər. Bu vəziyyətdə nəticə düzgündür, ancaq yaddaşdakı başqa bir şey pozulur.

Proqramlarda belə səhvlər olarsa, bütün bahislər əslində nə baş verəcəyinə əsaslanacaqdır.


cavab 2:

48 ədəd sıfırın ASCII təmsilçiliyi və 57 rəqəmi ASCII doqquz sayının təmsilidirsə, ən az əhəmiyyətli nibble əslində təmsil olunan saydır:

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ə ya sadə; sayı almaq üçün 48 çıxın.