Jak działa zapis pozycyjny w różnych systemach liczbowych
W systemie pozycyjnym wartość cyfry zależy od jej miejsca. System dziesiętny ma dziesięć cyfr, od 0 do 9, a kolejne pozycje mnożymy przez potęgi liczby 10, więc zapis 507 znaczy 5·10² + 0·10¹ + 7·10⁰. Ta sama zasada obowiązuje w każdej innej podstawie. Binarne 1011 to 1·2³ + 0·2² + 1·2¹ + 1·2⁰, czyli 11. Podstawa systemu mówi, ile różnych cyfr wchodzi w grę: dziesięć w podstawie 10, dwie w podstawie 2, osiem w podstawie 8 i szesnaście w podstawie 16.
Jak przeliczać liczby między podstawami
Zamiana w drugą stronę sprowadza się do kolejnego dzielenia z resztą. Dzielimy liczbę przez podstawę docelową, zapisujemy resztę, otrzymany wynik dzielimy ponownie i tak aż do zera. Reszty odczytane od ostatniej do pierwszej tworzą zapis liczby w nowym systemie. Tabela w kolumnie obok pokazuje te kroki dla wprowadzonej wartości dziesiętnej, więc widać, skąd bierze się każda cyfra.
Dlaczego BigInt jest tutaj konieczny
JavaScript przechowuje liczby jako wartości zmiennoprzecinkowe podwójnej precyzji. Daje to 53 bity mantysy, więc liczby całkowite są odwzorowane bez błędu do 9 007 199 254 740 991, czyli 2⁵³ − 1. Powyżej tej granicy dokładność znika. Kolejne wartości zaczynają się „sklejać”, bo dodanie jedynki do 2⁵³ niczego już nie zmienia.
Dla konwertera systemów liczbowych ma to poważne konsekwencje. Implementacja oparta na parseInt i toString zwróci dla 64-bitowego identyfikatora albo maski bitowej wartość błędną, i to bez żadnego ostrzeżenia. Typ BigInt, dodany do języka w 2020 roku, przechowuje liczby całkowite o dowolnej długości i wykonuje na nich działania dokładnie. Wszystkie obliczenia w tym narzędziu idą właśnie przez niego, co sprawdzisz, wprowadzając liczbę o trzydziestu cyfrach.
Operacje bitowe w praktyce
Koniunkcja bitowa AND służy najczęściej do maskowania, bo wynik zachowuje wyłącznie bity ustawione w obu argumentach. Alternatywa OR ustawia bity, a różnica symetryczna XOR je przełącza, stąd jej popularność w prostym szyfrowaniu i w sumach kontrolnych. Przesunięcie w lewo o jedną pozycję mnoży przez dwa, przesunięcie w prawo dzieli przez dwa z zaokrągleniem w dół. Sekcja operacji bitowych pracuje więc jak kalkulator, który ten sam wynik pokazuje od razu w czterech systemach liczbowych.
Typowe zastosowanie to flagi upakowane w jednej liczbie. Uprawnienia pliku w systemach uniksowych zapisane jako 644 to trzy grupy po trzy bity. Pierwszy bit w grupie oznacza odczyt, drugi zapis, trzeci uruchomienie, a same grupy odnoszą się kolejno do właściciela, jego grupy i pozostałych użytkowników. Sprawdzenie, czy właściciel może zapisywać, to operacja AND z maską 0o200. Podobnie czyta się pola bitowe w protokołach sieciowych i rejestry sterujące w elektronice, gdzie pojedynczy bit włącza konkretną funkcję układu.
Liczby ujemne i uzupełnienie do dwóch
Procesory zapisują liczby ujemne w kodzie uzupełnieniowym do dwóch, gdzie najstarszy bit oznacza znak, a wartość ujemna powstaje przez negację wszystkich bitów i dodanie jedynki. Odejmowanie sprowadza się wtedy do dodawania, a układ arytmetyczny jest prostszy. Zapis zależy jednak od szerokości słowa, bo liczba −1 to FF na ośmiu bitach i FFFFFFFF na trzydziestu dwóch.
BigInt nie ma ustalonej szerokości. Operuje na nieskończonym uzupełnieniu do dwóch, dlatego NOT z dwunastu daje minus trzynaście zamiast 243 czy 4294967283. Jeśli potrzebujesz wyniku dla konkretnej szerokości rejestru, weź resztę z dzielenia przez 2 do potęgi równej liczbie bitów. Panel właściwości pokazuje, ile bitów zajmuje wprowadzona wartość.
Tekst jako ciąg bitów
Komputer nie przechowuje liter. Trzyma liczby, a standard Unicode przypisuje każdemu znakowi numer, natomiast kodowanie decyduje, jak ten numer zapisać w bajtach. W UTF-8 znaki alfabetu łacińskiego zajmują jeden bajt i są zgodne ze starym kodem ASCII, znaki z ogonkami dwa bajty, większość znaków chińskich trzy, a emoji cztery.
To wyjaśnia, dlaczego polski tekst waży w plikach więcej niż angielski o tej samej liczbie znaków, i dlaczego wiadomość SMS z jedną polską literą skraca się ze 160 do 70 znaków, bo sieć przełącza się wtedy na kodowanie dwubajtowe. Konwerter na dole strony pokazuje ten mechanizm wprost: wpisz „a”, a potem „ą”, i porównaj długość obu zapisów binarnych.