Maskowanie bitów (Java)
Maska 2-bitowa
Do maskowania użyjemy operatora iloczynu bitowego &
.
Mamy dwie zmienne;
int x = 21
, czyli (10110)2
int maska = 2
, czyli (10)2
Po zastosowaniu maski:
x = x & maska
albo
x &= maska
otrzymujemy wynik
x = 2
Możemy to rozpisać w tablicy.
1 | 0 | 1 | 1 | 1 |
& | ||||
0 | 0 | 0 | 1 | 0 |
= | ||||
0 | 0 | 0 | 1 | 0 |
Wszystkie bity na lewo do ostatniej jedynki (1) w masce są zawsze zerami, niezależnie od tego ile bitowa jest sama liczba.
Z logiki wiemy, że koniunkcja zwraca true
(1) tylko wtedy gdy obie strony koniunkcji mają wartość true (1).
W pozostałych przypadkach zwraca false
(0). To oznacza, że faktycznie ważne sa tylko te miejsca liczby w których maska ma liczbę 1 i tylko te bity liczby znajdą się w wyniku.
Po wykonaniu maskowania wynik ma tyle bitów ile miała maska. W naszym przypadku 2 bity, czyli (10)2 i jest to liczba 2.
Kod Java:
package binaria; public class BinAria02 { public static void main(String[] args) { int a = 22; System.out.println(Integer.toBinaryString(a)); int b = 2; System.out.println(Integer.toBinaryString(b)); a = (byte)(a & b); System.out.println(a); } }
Po uruchomieniu na konsoli zobaczymy:
10110 10 2
Maska 1-bitowa
Sprawdzanie parzystości Java jest przykładem użycia maski (1)2
Maska 8-bitowa
Bardzo często używa się maski do wycięcia z liczby np. 32-bitowej ostatnich 8 bitów:
x &= 0377
, czyli (11111111)2. (Czołowe 0 oznacza, że liczba jest ósemkowa). Można oczywiście 🙂 zastosować maskę (255)10
int a = 1234567; System.out.println(Integer.toBinaryString(a)); int b = 0377; System.out.println(Integer.toBinaryString(b)); a = (int) (a & b); System.out.println(a); System.out.println(Integer.toBinaryString(a));
Po uruchomieniu kodu (BinAria03.java) na konsoli otrzymamy
100101101011010000111 11111111 135 10000111
Maska 8-bitowa przesuwna
W języku Java kolor mozna wyrażać pojedynczą liczbą int
.
Przykładem może być 'kolor koloru koralowego’ 🙂 czyli (16744272)10 = (111111110111111101010000)2
= (ff7f50)16.
Powstaje pytanie jak odczytać wartości składowe koloru rgb (red, green, blue). Użyjemy operatora bitowego przesunięcia w prawo oraz maski (0377), składającej się binarnie z 8 jedynek.
Dla blue nie ma przesunięcia, dla green przesuniecie wynosi 8, dla red przesunięcie wynosi 16.
A oto stosowny kod (BinAria04.java);
int rgb = 16744272; System.out.println(Integer.toBinaryString(rgb)); int maska = 0377; int r = (rgb >> 16) & maska; int g = (rgb >> 8) & maska; int b = (rgb >> 0) & maska; System.out.println("r = " + r + " = " + Integer.toBinaryString(r)); System.out.println("g = " + g + " = 0" + Integer.toBinaryString(g)); System.out.println("b = " + b + " = 0" + Integer.toBinaryString(b)); System.out.println(Integer.toHexString(rgb));
Po uruchomieniu tego kodu na konsoli zobaczymy:
111111110111111101010000 r = 255 = 11111111 g = 127 = 01111111 b = 80 = 01010000 ff7f50
Maska hexa
Maska może być liczbą heksadecymalną.
(0377)8 = (0xff)16
A oto powyższy przykład nieco przerobiony (BinAria05.java):
int rgb = 16744272; System.out.println(Integer.toBinaryString(rgb)); int r = (rgb >> 16) & 0xff; int g = (rgb >> 8) & 0xff; int b = (rgb >> 0) & 0xff; System.out.println(r); System.out.println(g); System.out.println(b);
Po uruchomieniu kodu na konsoli otrzymujemy:
111111110111111101010000 255 127 80