Kalkulator binarny (dwójkowy)
2019-10-22 / Krzysztof Kozłowski

Tym razem pokazujemy, jak w Javie napisać program do zamiany liczb dziesiętnych na binarne (dwójkowe) i binarnych na dziesiętne.

Trochę teorii

Zacznijmy od przypomnienia sobie, co to jest liczba dwójkowa i dwójkowy system liczbowy? Wbrew pozorom jest on prostszy od systemu dziesiętnego, którym posługujemy się na co dzień, ponieważ zamiast dzisięciu cyfr wykorzystujemy tylko dwie cyfry: 0 i 1. Dziesiętny jest dla nas naturalny, ponieważ od wieków liczymy na palcach, a tych mamy 10 :)

Dwójkowy system liczbowy wykorzystuje dwie cyfry 0 i 1. Wartość liczby wyliczamy podobnie, jak w systemie dziesiętnym, czyli w zależności od pozycji cyfry. Jedyna różnica to, że na kolejnych pozycjach mamy do czynienia z potęgami liczby 2, a nie 10.

Przykład

Prosty przykład powienien rozjaśnić, o co chodzi.

Liczbę dwójkową 1100111 chcemy zamienić na liczbą dziesiętną. Analizujemy ją od prawej do lewej sumując kolejne potęgi liczby dwa.

Liczba dwójkowa $1100111 = 1 ⋅ 2^6 + 1 ⋅ 2^5 + 0 ⋅ 2^4 + 0 ⋅ 2^3 + 1 ⋅ 2^2 + 1 ⋅ 2^0 = 103$

Przeliczanie z systemu dziesiętnego na binarny

Aby z liczby dziesiętnej uzyskać liczbę binarną (czyli zapisaną w systemie dwójkowym) wystarczy ją dzielić przez 2 i zapisywać kolejne reszty z dzielenia przez 2 (reszta z dzielenia przez dwa może dać tylko dwa wyniki: 0 lub 1). Dzielenie wykonujemy tak długo, aż wynik z dzielenia będzie liczbą mniejszą niż 1.

Wyniki kolejnych dzieleń najwygodniej zapisywać w słupku, gdzie obok każdego dzielenia zapisujemy także reszty z dzielenia przez 2. Zapisane reszty - czytane od dołu do góry - dadzą nam wynik, czyli liczbę binarną uzyskaną z liczby dziesiętnej.

Liczba dziesiętna 103 to binarnie 1100111

Program

Czas na program, który na tej podstawie wykona obliczenia i umożliwi konwersję liczb.

W tym celu napiszemy aplikację konsolową, w której zdefiniujemy dwie funkcje: jedną do konwersji liczb dziesiętnych na binarne i drugą do konwersji liczb binarnych na dziesiętne.

Zamiana liczby dzisiętnej na binarną

1
2
3
4
5
6
7
8
9
10
public static String toBinary(int decimalNumber) {
String binaryNumber = ""; // liczba binarna

while (decimalNumber > 0) {
binaryNumber = (decimalNumber % 2) + binaryNumber;
decimalNumber /= 2;
}

return binaryNumber;
}

W powyższej funkcji korzystamy z pętli WHILE, w której tak długo dzielimy liczbę przez 2, aż uzyskany wynik z dzielenia całkowitego nie będzie zerowy. Jest to odzwierciedlenie operacji, które ręcznie robiliśmy w słupku powyżej.

W linii 5 znajduje się zapis:

1
decimalNumber % 2

Oznacza on tzw. operację Modulo czyli wyznaczanie reszty z dzielenie jednej liczby przez drugą. W przypadku dzielenie dzielenia przez 2 reszta może wynosić 0 lub 1.

Linia 6:

1
decimalNumber /= 2;

jest skrótem i oznacza to samo, co możnaby zapisać w następujący sposób:

1
decimalNumber = decimalNumber / 2;

Zamiana liczby binarnej na dziesiętną

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public static int toDecimal(String binaryNumber) {
int decimalNumber = 0; // liczba dzisiętna
int power = 1; // kolejna potęga liczby 2 wynikająca z pozycji znaku
int value; // wartość liczbowa znaku, np. wartość liczbowa znaku '0' = 0, '1' = 1

for (int i = binaryNumber.length() - 1; i >= 0; i--) {

// konwersję znaku na liczbę możemy dokonać na 3 różne sposoby:
// value = binaryNumber.charAt(i) - '0';
// value = Integer.valueOf(binaryNumber.substring(i, i + 1)).intValue();
value = Character.getNumericValue(binaryNumber.charAt(i));

decimalNumber += (value * power);

power *= 2;
}

return decimalNumber;
}

Zamiana liczby binarnej na dziesiętną polega na analizowaniu kolejnych znaków (czy mamy do czynienia z cyfrą 0 czy 1) i wyliczeniu na tej podstawie kolejnych potęg liczby 2, które w każdym przebiegu pętli sumujemy (w linii nr 12).

Warto wyjaśnić, co dzieje się w linii 10 funkcji toDecimal()

Zapis:

1
value = Character.getNumericValue(binaryNumber.charAt(i));

oznacza pobranie kolejnego znaku liczby binarnej (binaryNumber.charAt(i)) i przekonwertowaniu go na liczbę 0 lub 1. W tym celu wykorzystujemy gotową funkcję Character.getNumericValue(). Zakomentowane linie nr 8 i 9 zawierają tę samą operację (czyli konwersję znaku na liczbę), ale zrealizowaną nieco inaczej. I zwykle tak jest, że daną rzecz można zrealzować na kilka różnych sposóbów, z których każdy jest poprawny.

Linia 15:

1
power *= 2

to ponownie skrót instrukcji, którą można zapisać w inny - nieco dłuższy - sposób:

1
power = power * 2

Zmienna power przechowuje informację o kolejnej potędze liczby 2, dlatego po każdym przebiegu pętli ponownie mnożymy ją przez 2 i w ten sposób otrzymujemy wartość kolejnej potęgi liczby 2. Korzystamy tu z faktu, że $2^{n+1} = 2^n ⋅ 2$

Pełny kod programu

Poniżej pełny kod programu wraz z przykładem wywołania obu funkcji.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
public class Main {

public static String toBinary(int decimalNumber) {
String binaryNumber = ""; // liczba binarna

while (decimalNumber > 0) {
binaryNumber = (decimalNumber % 2) + binaryNumber;
decimalNumber /= 2;
}

return binaryNumber;
}

public static int toDecimal(String binaryNumber) {
int decimalNumber = 0; // liczba dzisiętna
int power = 1; // kolejna potęga liczby 2 wynikająca z pozycji znaku
int value; // wartość liczbowa znaku, np. wartość liczbowa znaku '0' = 0, '1' = 1

for (int i = binaryNumber.length() - 1; i >= 0; i--) {

// konwersję znaku na liczbę możemy dokonać na 3 różne sposoby:
// value = binaryNumber.charAt(i) - '0';
// value = Integer.valueOf(binaryNumber.substring(i, i + 1)).intValue();
value = Character.getNumericValue(binaryNumber.charAt(i));

decimalNumber += (value * power);

power *= 2;
}

return decimalNumber;
}

public static void main(String[] args) {
System.out.println("=== Zamiana liczb dziesiętnych na binarne ===");
System.out.println("15 w systemie binarnym to " + toBinary(15));
System.out.println("16 w systemie binarnym to " + toBinary(16));
System.out.println("17 w systemie binarnym to " + toBinary(17));
System.out.println("1023 w systemie binarnym to " + toBinary(1023));
System.out.println("1024 w systemie binarnym to " + toBinary(1024));
System.out.println("1025 w systemie binarnym to " + toBinary(1025));

System.out.println("");

System.out.println("=== Zamiana liczb binarnych na dziesiętne ===");
System.out.println("1111 w systemie binarnym to " + toDecimal("1111"));
System.out.println("10000 w systemie binarnym to " + toDecimal("10000"));
System.out.println("10001 w systemie binarnym to " + toDecimal("10001"));
System.out.println("1111111111 w systemie binarnym to " + toDecimal("1111111111"));
System.out.println("10000000000 w systemie binarnym to " + toDecimal("10000000000"));
System.out.println("10000000001 w systemie binarnym to " + toDecimal("10000000001"));
}
}

Wynik działania programu:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
=== Zamiana liczb dziesiętnych na binarne ===
15 w systemie binarnym to 1111
16 w systemie binarnym to 10000
17 w systemie binarnym to 10001
1023 w systemie binarnym to 1111111111
1024 w systemie binarnym to 10000000000
1025 w systemie binarnym to 10000000001

=== Zamiana liczb binarnych na dziesiętne ===
1111 w systemie binarnym to 15
10000 w systemie binarnym to 16
10001 w systemie binarnym to 17
1111111111 w systemie binarnym to 1023
10000000000 w systemie binarnym to 1024
10000000001 w systemie binarnym to 1025

Program można również przetstować online pod adresem https://repl.it/@toudidel/Kalkulator-binarny (program uruchamiamy klawiszem run u góry ekranu).

PermaLink: https://java.kozlowski.photos/2019/10/kalkulator-binarny/