Skocz do zawartości
  • 👋 Witaj na MPCForum!

    Przeglądasz forum jako gość, co oznacza, że wiele świetnych funkcji jest jeszcze przed Tobą! 😎

    • Pełny dostęp do działów i ukrytych treści
    • Możliwość pisania i odpowiadania w tematach
    • System prywatnych wiadomości
    • Zbieranie reputacji i rozwijanie swojego profilu
    • Członkostwo w jednej z największych społeczności graczy

    👉 Dołączenie zajmie Ci mniej niż minutę – a zyskasz znacznie więcej!

    Zarejestruj się teraz

Prośba o wytlumaczenie operatorów bitowych


Rekomendowane odpowiedzi

Opublikowano

Siemka, od niedawna przerzucilem sie na jave z c++(z czego i tak umialem podstawy), Obejrzałem polski poradnik dotyczacy Javy, i troszke "liznąłem" GUI. Jednak postanowilem uzupelnić swoja wiedze z poradnika SUN/ORRACLA.

Prosze o wytłumaczenie mi tych operatorów z prostymi programami pokazujacymi ich zastosowanie.

~       <<      >>      >>>     &       ^       |       

oraz objasnienie dzialania tego programu:

 

class BitDemo {
    public static void main(String[] args) {
        int bitmask = 0x000F;
        int val = 0x2222;
        // prints "2"
        System.out.println(val & bitmask);
    }
}

 

bitmask przypisujemy wartosc w systemie szesnastkowym, wiec bitmask ma wartosc 15(15* 16 do potegi 0). A co robimy z val? w jakkim systemie przypisujemy i jaka wartosc?

i czemu wydrukowuje wartosc 2?

 

 

Opublikowano

Zacznę od operatorów - są one bardzo proste, google bez problemu Ci je wytłumaczy. Teraz czas na bitmask. Wszystko trzeba zmienić na binarny:





bitmask -  00000000001111
val -      10001000100010

Operator & porównuje po kolei bity i jeśli w obydwu bitach znajduje się 1, to zwraca jeden. Czyli:





0 & 1 = 0
0 & 0 = 0
1 & 0 = 0
1 & 1 = 1

Jeślli zaczniesz porównywać tak bitmask z val, to zauważysz że 1 może zwrócić tylko wtedy, gdy w bitmask w danym bicie jest 1. Czyli zapisze Ci tylko 4 pierwsze bity:





10001000100010 &
00000000001111
--------------
00000000000010

a 10 w binarnym = 2. Często używa się bitmask, aby zapisać kilka liczb w jednej - przy użyciu przesunięć bitowych (>> lub <<), które działają też bardzo banalnie.

708121422388637873334.png

Opublikowano

A propo operatórów >> i >>> bo z nimi jest trochę bardziej skomplikowanie.

>> dodaje bit znaku na początku

>>> dodaje 0 na początku

 

O wszystkim możesz poczytać tu

http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.19

 

 

@edit.

Wszystko w komputerze bazuje na systemie binarnym.

Opublikowano

Ok panowie wytlumaczyli już o co w tym biega ja podam parę zastosowań:


1.Tak jak jaca wspomniał zapisywanie kilku wartości w jednej która jest wieksza a nie chcemy marnować danych, np kolory.

Kolor składa się z 31 bajtów (8 bitów) 0-255 R,G,B albo B,R,G nieważne, ważne ze są 3 

3 Bajty czyli 3*8 = 24 bity więc możemy te 3 bajty zmieścić w 1 incie bo int w javie ma 32 bity

Problem w tym że java nie pozwala nam na łatwe użycie  bajtu bez znaku czyli takiego zawsze na plusie. My taki chcemy bo potrzebujemy wartości od 0-255, a bajt ze znakiem bedzie miał od -128 do 127, z pomocą przychodzi nam & i upcast, czyli rzutowanie do góry, np bajt na short, bajt na int. Dlaczego musimy go rzucić do góry? Dlatego że w javie jak już wspomniałem nie ma magicznej wartości która będzie nam mówić czy bajt jest ze znakiem czy nie, 
każdy prymityw (byte,int,long) jest z góry ze znakiem, reprezentacja liczb w javie to tzw Two's complement.
Teraz tak, przykład:
Mamy bajt

byte b = 255; - kompilator wyrzuci nam błąd bo jak wspomniałem nie pozwala na przypisanie wartości powyżej 127, wystarczy zrobić:
byte b = (byte)255; - zmuszamy przypisanie 255 do bajtu, ale teraz co się dzieje:

sout( B) - wyświetli nam -1 bo wcale nie zmieniliśmy reprezentacji bitów i java czyta dalej jako ze znakiem.

255 binarnie to oczywiście 1111 1111 tylko że jeśli java czyta to za pomocą two's complement to:

2014-04-26_18-12-59.png

Dla niej jest to -1 dec.

Enc tak, chcemy teraz wyświetlić sobie nie -1 tylko 255, potrzebujemy mianowicie jednego dodatkowego bitu który ustalimy na 0, dlaczego tak? Zapraszam do lektury : http://en.wikipedia.org/wiki/Two's_complement. 

Dobra wiec bierzemy sobie coś co ma więcej niż 8 bitów powiedzmy że shorta (16bit), ok mamy shorta, teraz co z nim:

Jeśli zapiszemy w shorcie wartość 255 to binarnie bd to wyglądało :

0000 0000 1111 1111

Ok, ale my potrzebujemy zapisać bajt w shorcie.

Spróbujmy zcastować bajt do shorta short s = (short)bajt; Ale też nam to nijjak pomogło bo short będzie teraz miał:

1111 1111 1111 1111 - Dlaczego? dlatego że nasz bajt dalej jest -1 a -1 jako short właśnie tak wygląda ;(, więc praktycznie robiliśmy (short)-1;

No dobra to jak?! Ano tak, mamy operator &, który działa jak już wspomniał jaca, enc tak:

Wróćmy do poprzedniego castu, zwrócił on nam:

1111 1111 1111 1111

A my chcemy

 

0000 0000 1111 1111

Jak tego dokonać ;O, ano tak:

1111 1111 1111 1111 

&

0000 0000 1111 1111
=

0000 0000 1111 1111

Boshe ale jak to napisać? Tak samo jak u góry ;3 Czyli od poczatku:
byte red = (byte)255;

sout((short) green & 0xFF)) - i nam wyświetli upragnione "255".

No dobra ale mówiłeś że możemy dzięki temu zapisać kilka wartości w 1 incie, a zrobiłeś kompletnie na odwrót ! Nub!

Taa, na razie pokazałem jak usunąć bit znaku w bajcie, dzięki temu mamy już praktycznie wstawiony jeden bajt w shorcie, nie pokażę ci jak wstawić 3 bajty do int hehe pokażę ci jak to robić, jak zrozumiesz dasz sobie radę.
OK! Drugi bajt!

Więc nasz short ma już wartość binarną 0000 0000 1111 1111

dajmy na to że 1 bajt to jest nasz kolor uhm czerwony czyli 255, teraz wstawimy sobie 2 kolor "zielony" o wartości dec 128. Więc mamy narazie tak:
byte red = (byte)255;

 

short color = (short) ((short) red & 0xFF);
Jak teraz wstawić następnego bajta? tak samo tylko że musimy trochę przesunąć nasze wstawianie, do tego posłuży nam operator "<<"
Co u diabła to robi? Przykład:

bajt = 0000 1111.
i zrobimy na nim << 1, to uzyskamy
bajt = 0001 1110

damy << 2 na wejsciowym czyli 0000 1111
bajt = 0011 1100
damy << 2 na poprzednim wyniku czyli 0011 1100

bajt = 1111 0000.
Po prostu przesuwany dane o x w lewo

to samo się tyczy >> tylko że na odwrót ;3
No jak nie zrozumiałeś to sory ale infa nie dla ciebie ;/ (Nie wiem kto by tego nie zczaił)

no dobra to wstawiamy:

 

Short green ma 0000 0000 1000 0000

A short koloru ma 0000 0000 1111 1111
Chcemy wstawić 128 na 2 bajcie kolor czyli musimy przesunąć shorta zielonego o ? hehe tak, o 8 bitów

Dobre, to mamy

byte red = (byte)255;

byte green= (byte)128;

 

short color = (short) ((short) green << 8 | (short) red & 0xFF);

 

!! Tam jest "|" , po co to? Ano poto że:

 

Stadium 1:

Short koloru ma poczatkową wartość: 

                          0000 0000 0000 0000

Short green ma 0000 0000 1000 0000
Short red ma     0000 0000 1111 1111

Stadium 2: (przesuwamy greena o 8 bitów)

 

Short koloru ma poczatkową wartość: 

                          0000 0000 0000 0000

 

Short green ma 1000 0000 0000 0000
Short red ma     0000 0000 1111 1111

 

Stadium 3: (Wykonujemy or (|) na greenie i redzie:

 

Short koloru ma poczatkową wartość: 

                          0000 0000 0000 0000

 

Short green ma 1000 0000 0000 0000

|
Short red ma     0000 0000 1111 1111

=

Wynik ma          1000 0000 1111 1111
2014-04-26_19-13-57.png

Stadium 4:
Przyrównujemy wynik do shorta, i gotowe mamy shorta z 2 bajtami (1000 0000 i 1111 1111)
Ale teraz jak to odczytać? ANALogicznie:
 

short kolor = (short) ((short) green << 8 | (short) red & 0xFF);
 

        short green = (short) ((s >> 8) & 0xFF);
        short red = (short) (s & 0xFF);

Ot cała filozofia, teraz zadanie dla Ciebie, zapisać 4 bajty (R,G,B,A) w incie i odczytać, jak napiszesz możesz się pochwalić :)
 
PS. Nabazgrolone jak zawsze ale myślę że jednak coś z tego zrozumiesz ;)


@Edit
Apropos '~' to po prostu zamienia 0 na 1 i 1 na 0

np 1111 1110, ~1111 1110 = 0000 0001

Uzycie:
Np masz inta gdzie przechowywujesz maski i chcesz usunąć jakąś to robisz maska &= ~wartośćMaski;
(za kija nie wiem jak to sie po polsku nazywa ;o "maska")

2014-04-26_19-46-10.png
Opublikowano

 

public class BaAnnalne {

    public static void main(String[] args) {
    int R,G,B,A;
        R=0xF;//w systemie 16(F=15 w dziesietnym,1111 w binarce)
        G=R>>1;//w systemie binarnym ma postac 0111
        B=~G;//crach
        A=R|G;//uzywamy OR na R i B
        
        System.out.println("r:"+R);
        System.out.println("g:"+G);
        System.out.println("b:"+;//bład
        System.out.println("a:"+A);


    }

}

w B powinno zanegowac G i wypisac wartosc (w binarnym)1000

nwm czy oto chodzilo czy nie

Opublikowano
public class BaAnnalne {

    public static void main(String[] args) {
    int R,G,B,A;
        R=0xF;//w systemie 16(F=15 w dziesietnym,1111 w binarce)
        G=R>>1;//w systemie binarnym ma postac 0111
        B=~G;//crach
        A=R|G;//uzywamy OR na R i B
        
        System.out.println("r:"+R);
        System.out.println("g:"+G);
        System.out.println("b:"+;//bład
        System.out.println("a:"+A);


    }

}

w B powinno zanegowac G i wypisac wartosc (w binarnym)1000

nwm czy oto chodzilo czy nie

 

Um nwm, moze zesmy sie zle zrozumieli ale mi chodziło o :

 

2014-04-27_00-46-33.png

 

A odnosnie twojego kodu to, G ma 32 bity bo jest intem czyli to nie jest 0111 tylko 0000 0000 0000 0000 0000 0000 0000 0111

wiec jak na tym dasz ~ to sam już zreszta wiesz dlaczego tak masz :D

Zeby dzialalo tak jak ty chcesz to musisz na tym jeszcze zrobic & 0xF

0000 0000 0000 0000 0000 0000 0000 0111

~

1111 1111 1111 1111 1111 1111 1111 1000

&

0000 0000 0000 0000 0000 0000 0000 1111

=

0000 0000 0000 0000 0000 0000 0000 1000

 

Rozumiesz?

 

Zarchiwizowany

Ten temat przebywa obecnie w archiwum. Dodawanie nowych odpowiedzi zostało zablokowane.

×
×
  • Dodaj nową pozycję...