Rozważ dziesiętną wartość całkowitą, taką jak 5623. Intuicyjnie rozumiemy, że te cyfry oznaczają (5 * 1000) + (6 * 100) + (2 * 10) + (3 * 1). Ponieważ jest 10 liczb dziesiętnych, wartość każdej kolejnej cyfry po lewej stronie zwiększa się 10-krotnie.
Liczby binarne działają w ten sam sposób, z tą różnicą, że są tylko 2 cyfry binarne (0 i 1), więc wartość każdej cyfry zwiększa się 2-krotnie. Podobnie jak przecinki są często używane, aby ułatwić odczytanie dużej liczby dziesiętnej (np. 1 427 435), często piszemy liczby binarne w grupy po 4 bity, aby ułatwić ich odczytanie (np. 1101 0101).
Poniższa tabela liczy do 15 w systemie dziesiętnym i binarnym:
| Wartość dziesiętna | Wartość binarna |
|---|---|
| 0 | 0 |
| 1 | 1 |
| 2 | 10 |
| 3 | 11 |
| 4 | 100 |
| 5 | 101 |
| 6 | 110 |
| 7 | 111 |
| 8 | 1000 |
| 9 | 1001 |
| 10 | 1010 |
| 11 | 1011 |
| 12 | 1100 |
| 13 | 1101 |
| 14 | 1110 |
| 15 | 1111 |
Konwersja binarna na dziesiętną
W poniższych przykładach zakładamy, że mamy do czynienia z liczbą bez znaku liczby całkowite.
Rozważ 8-bitową (1 bajt) liczbę binarną 0101 1110. Binarna liczba 0101 1110 oznacza (0 * 128) + (1 * 64) + (0 * 32) + (1 * 16) + (1 * 8) + (1 * 4) + (1 * 2) + (0 * 1). Jeśli podsumujemy wszystkie te części, otrzymamy liczbę dziesiętną 64 + 16 + 8 + 4 + 2 = 94.
Oto ten sam proces w formie tabeli. Mnożymy każdą cyfrę binarną przez jej wartość cyfrową (określoną przez jej pozycję). Sumując wszystkie te wartości otrzymujemy sumę.
Konwersja 0101 1110 na dziesiętny:
| Cyfra binarna | 0 | 1 | 0 | 1 | 1 | 1 | 1 | 0 |
| * Wartość cyfry | 128 | 64 | 32 | 16 | 8 | 4 | 2 | 1 |
| = Razem (94) | 0 | 64 | 0 | 16 | 8 | 4 | 2 | 0 |
Przeliczmy 1001 0111 na dziesiętne:
| Cyfra binarna | 1 | 0 | 0 | 1 | 0 | 1 | 1 | 1 |
| * Wartość cyfry | 128 | 64 | 32 | 16 | 8 | 4 | 2 | 1 |
| = Suma (151) | 128 | 0 | 0 | 16 | 0 | 4 | 2 | 1 |
1001 0111 dwójkowa = 151 w postaci dziesiętnej.
Można to łatwo rozszerzyć do 16 lub 32-bitowych liczb binarnych, po prostu dodając więcej kolumn. Pamiętaj, że najłatwiej jest zacząć od prawej strony i kierować się w lewo, mnożąc wartość cyfry przez 2.
Metoda 1 konwersji postaci dziesiętnej na binarną
Konwersja z postaci dziesiętnej na binarną jest nieco trudniejsza, ale wciąż całkiem prosta. Jest na to kilka dobrych metod.
W tej pierwszej metodzie stale dzielisz przez 2, a resztę zapisujesz. Liczbę binarną konstruuje się na końcu z reszt, od dołu do góry.
Konwersja 148 z postaci dziesiętnej na binarną (używając r do oznaczenia reszty):
148 / 2 = 74 r0
74 / 2 = 37 r0
37 / 2 = 18 r1
18 / 2 = 9 r0
9 / 2 = 4 r1
4 / 2 = 2 r0
2 / 2 = 1 r0
1 / 2 = 0 r1
Zapisywanie wszystkich pozostałych od dołu do góry: 1001 0100
148 dziesiętne = 1001 0100 binarne.
Możesz zweryfikować tę odpowiedź, konwertując liczbę binarną z powrotem na dziesiętną:
(1 * 128) + (0 * 64) + (0 * 32) + (1 * 16) + (0 * 8) + (1 * 4) + (0 * 2) + (0 * 1) = 148
Ta metoda jest najlepsza dla ludzi, ponieważ wymaga tylko dzielenia przez 2. Jest mniej dobra dla maszyn, ponieważ wymaga przechowywania wszystkich bitów w miarę ich obliczania, aby można je było wydrukować później odwróć kolejność.
Metoda 2 konwersji liczby dziesiętnej na binarną
W pozostałych dwóch metodach będziemy pracować dalej, obliczając każdy bit w miarę upływu czasu, tak że nie będziemy musieli na końcu rekonstruować liczby binarnej.
Rozważmy ponownie liczbę dziesiętną 148. Największa potęga liczby 2 mniejsza niż 148 to 128, więc zaczniemy od tego.
Czy 148 >= 128? Tak, więc 128 bitów musi wynosić 1. 148 - 128 = 20, co oznacza, że musimy znaleźć bity warte o 20 więcej.
Czy 20 >= 64? Nie, więc 64 bity muszą mieć wartość 0.
Czy 20 >= 32? Nie, więc 32 bity muszą mieć wartość 0.
Czy 20 >= 16? Tak, więc 16 bitów musi wynosić 1. 20 - 16 = 4, co oznacza, że musimy znaleźć bity warte o 4 więcej.
Czy 4 >= 8? Nie, więc 8 bitów musi wynosić 0.
Czy 4 >= 4? Tak, więc 4 bity muszą wynosić 1. 4 - 4 = 0, co oznacza, że wszystkie pozostałe bity muszą wynosić 0.
148 = (1 * 128) + (0 * 64) + (0 * 32) + (1 * 16) + (0 * 8) + (1 * 4) + (0 * 2) + (0 * 1) = 1001 0100
W formacie tabeli:
| Liczba binarna | 1 | 0 | 0 | 1 | 0 | 1 | 0 | 0 |
| * Wartość cyfry | 128 | 64 | 32 | 16 | 8 | 4 | 2 | 1 |
| = Razem (148) | 128 | 0 | 0 | 16 | 0 | 4 | 0 | 0 |
Ta metoda jest dość łatwa dla ludzi, gdy liczby są małe (np. dla 8-bitowych liczb binarnych). Jest to również dość wydajne w przypadku maszyn, ponieważ każdy bit wymaga porównania, odjęcia i przypisania.
Metoda 3 konwersji liczby dziesiętnej na binarną
Ta metoda jest wariantem metody 2, która wykorzystuje dzielenie liczb całkowitych. Consider the decimal number 148 yet again. Największa potęga liczby 2, która jest mniejsza niż 148, to 128, więc od tego zaczniemy.
148 / 128 = 1 z pewną resztą. Ponieważ 1 jest nieparzyste, ten bit ma wartość 1.
148 / 64 = 2 z pewną resztą. Ponieważ 2 jest parzyste, ten bit wynosi 0.
148 / 32 = 4 z pewną resztą. Ponieważ 4 jest parzyste, ten bit wynosi 0.
148 / 16 = 9 z pewną resztą. Ponieważ 9 jest nieparzyste, ten bit ma wartość 1.
148 / 8 = 18 z pewną resztą. Ponieważ 18 jest parzyste, ten bit wynosi 0.
148 / 4 = 37 z pewną resztą. Ponieważ 37 jest nieparzyste, ten bit to 1.
148 / 2 = 74 z pewną resztą. Ponieważ 74 jest parzyste, ten bit wynosi 0.
148 / 1 = 148 z pewną resztą. Ponieważ 148 jest parzyste, tym bitem jest 0.
148 = (1 * 128) + (0 * 64) + (0 * 32) + (1 * 16) + (0 * 8) + (1 * 4) + (0 * 2) + (0 * 1) = 1001 0100
Ta metoda nie jest dobra dla ludzi, ponieważ wymaga dużo dzielenia. Jest również mniej wydajny w przypadku maszyn, ponieważ dzielenie jest operacją nieefektywną. Ale łatwo jest to napisać w kodzie, ponieważ nie wymaga instrukcji if.
Kolejny przykład
Przekonwertujmy 117 na binarną metodą 1:
117 / 2 = 58 r1
58 / 2 = 29 r0
29 / 2 = 14 r1
14 / 2 = 7 r0
7 / 2 = 3 r1
3 / 2 = 1 r1
1 / 2 = 0 r1
Konstruowanie liczby z reszt od dołu do góry, 117 = 111 0101 binarny
I metodą 2:
Największa potęga 2 mniejsza niż 117 to 64.
Czy 117 >= 64? Tak, więc 64-bitowy musi wynosić 1. 117 - 64 = 53.
Czy 53 >= 32? Tak, więc 32-bitowy musi wynosić 1. 53 - 32 = 21.
Czy 21 >= 16? Tak, więc 16 bitów musi wynosić 1. 21 - 16 = 5.
Czy 5 >= 8? No, so the 8 bit must be 0.
Is 5 >= 4? Tak, więc 4 bity muszą wynosić 1. 5 - 4 = 1.
Czy 1 >= 2? No, so the 2 bit must be 0.
Is 1 >= 1? Tak, więc 1 bit musi wynosić 1.
117 dziesiętnych = 111 0101 binarnych.
Dodawanie binarne
W niektórych przypadkach (za chwilę się o tym przekonamy) przydatna jest możliwość dodania dwóch liczb binarnych. Dodawanie liczb binarnych jest zaskakująco łatwe (może nawet łatwiejsze niż dodawanie liczb dziesiętnych), chociaż na początku może wydawać się dziwne, ponieważ nie jesteś do tego przyzwyczajony.
Rozważ dwie małe liczby binarne:
0110 (6 w systemie dziesiętnym) +
0111 (7 w systemie dziesiętnym)
Dodajmy je. First, line them up, as we have above. Następnie zaczynając od prawej i kończąc na lewej, dodajemy każdą kolumnę cyfr, tak jak to robimy w przypadku liczby dziesiętnej. Ponieważ jednak cyfrą binarną może być tylko 0 lub 1, są tylko 4 możliwości:
- 0 + 0 = 0
- 0 + 1 = 1
- 1 + 0 = 1
- 1 + 1 = 0, przenieś 1 do następnej kolumny
Zróbmy pierwszą kolumnę:
0110 (6 in decimal) + 0111 (7 in decimal) ---- 1
0 + 1 = 1. Łatwe.
Druga kolumna:
1 0110 (6 in decimal) + 0111 (7 in decimal) ---- 01
1 + 1 = 0, z przeniesieniem 1 do następnej kolumny
Trzecia kolumna:
11 0110 (6 in decimal) + 0111 (7 in decimal) ---- 101
To jest trochę trudniejsze. Zwykle 1 + 1 = 0, z jedynką przenoszoną do następnej kolumny. Jednakże mamy już 1 przeniesioną z poprzedniej kolumny, więc musimy dodać 1. W ten sposób otrzymamy 1 w tej kolumnie, a 1 zostanie przeniesione do następnej kolumny.
Ostatnia kolumna:
11 0110 (6 in decimal) + 0111 (7 in decimal) ---- 1101
0 + 0 = 0, ale jest przeniesiona 1, więc dodajemy 1. 1101 = 13 w systemie dziesiętnym.
Teraz, jak dodać 1 do dowolnej liczby binarnej (takiej jak 1011 0011)? Podobnie jak powyżej, tylko dolna liczba jest binarna 1.
11 (carry column) 1011 0011 (original binary number) 0000 0001 (1 in binary) --------- 1011 0100
Liczby ze znakiem i uzupełnienie do dwójki
W powyższych przykładach zajmowaliśmy się wyłącznie liczbami całkowitymi bez znaku. W tej sekcji przyjrzymy się, jak traktowane są liczby ze znakiem (które mogą być ujemne).
Liczby całkowite ze znakiem są zwykle przechowywane przy użyciu metody znanej jako uzupełnienie do dwóch. W uzupełnieniu do dwójki bit znajdujący się najbardziej na lewo (najbardziej znaczący) jest używany jako bit znaku. Bit znaku 0 oznacza, że liczba jest dodatnia (lub zero), a bit znaku 1 oznacza, że liczba jest ujemna.
Liczby ze znakiem dodatnim są reprezentowane w postaci binarnej, podobnie jak liczby dodatnie bez znaku (z bitem znaku ustawionym na 0).
Liczby ze znakiem ujemnym są przedstawiane w systemie binarnym jako bitowa odwrotność liczby dodatniej plus 1.
Konwersja liczby dziesiętnej na binarną (dwójki uzupełnienie)
Na przykład, oto jak reprezentujemy -5 w binarnym uzupełnieniu do dwójki:
Najpierw ustalamy binarną reprezentację dla 5: 0000 0101
Następnie odwracamy wszystkie bity: 1111 1010
Następnie dodajemy 1:1111 1011
Konwersja -76 na binarny:
Dodatnie 76 w binarnym: 0100 1100
Odwróć wszystkie bity: 1011 0011
Dodaj 1: 1011 0100
Dlaczego dodajemy 1? Rozważmy liczbę 0. Jeśli wartość ujemna byłaby po prostu przedstawiona jako odwrotność liczby dodatniej (tzw. „dopełnienie do jedynki”), 0 miałoby dwie reprezentacje: 0000 0000 (zero dodatnie) i 1111 1111 (zero ujemne). Dodanie 1 powoduje celowe przepełnienie liczby 1111 1111 i uzyskanie wartości 0000 0000. Zapobiega to dwóm reprezentacjom 0 i upraszcza część wewnętrznej logiki potrzebnej do wykonywania arytmetyki na liczbach ujemnych.
Konwersja binarna (dopełnienie do dwóch) na dziesiętną
Aby przekonwertować liczbę binarną z uzupełnieniem do dwóch z powrotem na dziesiętną, najpierw spójrz na bit znaku.
Jeśli bit znaku wynosi 0, po prostu przekonwertuj liczbę, jak pokazano powyżej dla liczb bez znaku.
Jeśli bit znaku wynosi 1, odwracamy bity, dodajemy 1, następnie konwertujemy na liczbę dziesiętną, a następnie ustawiamy liczbę dziesiętną na ujemną (ponieważ bit znaku był pierwotnie ujemny).
Na przykład, aby przekonwertować 1001 1110 z uzupełnienia do dwójki na liczba dziesiętna:
Podane: 1001 1110
Odwróć bity: 0110 0001
Dodaj 1: 0110 0010
Zamień na dziesiętny: (0 * 128) + (1 * 64) + (1 * 32) + (0 * 16) + (0 * 8) + (0 * 4) + (1 * 2) + (0 * 1) = 64 + 32 + 2 = 98
Ponieważ pierwotny bit znaku był ujemny, ostateczna wartość wynosi -98.
Istnieje inna metoda, którą łatwiej jest obliczyć ręcznie. W tej metodzie bit znaku reprezentuje wartość ujemną, wszystkie pozostałe bity reprezentują wartości dodatnie.
Podane: 1001 1110
Przelicz na dziesiętny: (1 * -128) + (0 * 64) + (0 * 32) + (1 * 16) + (1 * 8) + (1 * 4) + (1 * 2) + (0 * 1) = -128 + 16 + 8 + 4 + 2 = -98
Dlaczego typy mają znaczenie
Rozważ wartość binarną 1011 0100. Jaką wartość to reprezentuje? Prawdopodobnie powiedziałbyś 180 i gdyby to była liczba binarna bez znaku, miałbyś rację.
Gdyby jednak ta wartość została zapisana przy użyciu uzupełnienia do dwójki, wynosiłaby -76.
A gdyby wartość została zakodowana w inny sposób, mogłaby to być zupełnie inna wartość.
Skąd więc C++ wie, czy wydrukować zmienną zawierającą wartość binarną 1011 0100 jako 180 lub -76?
Jeśli tytuł sekcji tego nie zdradza, tutaj w grę wchodzą typy. Typ zmiennej określa zarówno sposób, w jaki wartość zmiennej jest kodowana do postaci binarnej, jak i dekodowana z powrotem do wartości. Jeśli więc typ zmiennej byłby liczbą całkowitą bez znaku, wiedziałby, że 1011 0100 jest standardowym plikiem binarnym i powinien zostać wydrukowany jako 180. Jeśli zmienna była liczbą całkowitą ze znakiem, wiedziałby, że 1011 0100 zostało zakodowane przy użyciu uzupełnienia do dwóch (teraz gwarantowane od C++ 20) i powinno zostać wydrukowane jako -76.
A co z konwersją liczb zmiennoprzecinkowych z/na binarny?
Sposób konwersji liczb zmiennoprzecinkowych z/na plik binarny jest nieco bardziej skomplikowany i prawdopodobnie nie będziesz musiał się o tym nigdy dowiedzieć. Jeśli jednak jesteś ciekawy, zobacz tę witrynę, która dobrze wyjaśnia szczegółowo temat.
Czas quizu
Pytanie nr 2
Przekonwertuj 93 na 8-bitową liczbę binarną bez znaku, stosując obie metody 1 i 2 powyżej.
Pytanie nr 3
Przekształć -93 na 8-bitową liczbę binarną ze znakiem (używając uzupełnienia do dwóch).
Pytanie #5
Przelicz 1010 0010 na liczbę dziesiętną ze znakiem (załóż uzupełnienie do dwójki).
Pytanie nr 6
Napisz program, który poprosi użytkownika o wprowadzenie liczby z zakresu od 0 do 255. Wypisz tę liczbę jako 8-bitową liczbę binarną (w postaci #### ####). Nie używaj żadnych operatorów bitowych. Nie używaj std::bitset.
Przypomnienie: std::uint8_t jest zwykle traktowany jako znak, a nie int. Może to powodować nieoczekiwane zachowanie, gdy jest używane z danymi wejściowymi lub wyjściowymi.

