hlmod.hu

Magyar Half-Life Mód közösség!
Pontos idő: 2024.11.07. 13:20



Jelenlévő felhasználók

Jelenleg 289 felhasználó van jelen :: 1 regisztrált, 0 rejtett és 288 vendég

A legtöbb felhasználó (1565 fő) 2020.11.21. 11:26-kor tartózkodott itt.

Regisztrált felhasználók: Google [Bot]az elmúlt 5 percben aktív felhasználók alapján

Utoljára aktív
Ahhoz hogy lásd ki volt utoljára aktív, be kell jelentkezned.



Az oldal teljeskörű
használatához regisztrálj.

Regisztráció

Kereső


Új téma nyitása Hozzászólás a témához  [1 hozzászólás ] 
Szerző Üzenet
 Hozzászólás témája: [TUT] Bitműveletek
HozzászólásElküldve:2015.12.23. 15:15 
Offline
Tiszteletbeli
Avatar

Csatlakozott:2015.04.10. 19:49
Hozzászólások:610
Megköszönt másnak: 53 alkalommal
Megköszönték neki: 147 alkalommal
Sziasztok,

Gondoltam ismét készülök nektek valami újdonsággal :D A fórumozók többsége szerintem már látott ilyen operátorokat: ^, |, ~, &... Azonban csak kevesen tudják mire is jók ezek, mit is csinálnak, ezért gondoltam, hogy röviden, tömören átrágom a dolgot. Elsősorban tisztázzuk az elméleti részét, majd miután ez meglenne próbálok gyakorlati példákat mutatni, hogy mire is jók ezek. Próbálok eléggé konyhanyelven fogalmazni, de nem ide nem árt, ha képben vagy az alapokkal ( Metál alapozói ).

Mire is jók ezek?
Ezek az operátorok lehetőséget adnak, hogy az egész számok bitjeit külön - külön tudjuk kezelni, ki - be "kapcsolni". Ezek megértéséhez jól jön, ha tisztában vagyunk a kettes ( bináris ) számrendszerrel, nem kell mindent tudni, de az azért nem árt, ha tudod, hogy csak a 0 és az 1 létezik, mint számjegy ebben a számrendszerben és hogy bármennyi nullát tolunk egy szám elé az nem változtatja az értékét.
( 0001 = 000001 = 1 ) Ha kicsit visszagondolsz a matekórákra rögtön beugorhat, hogy miért is van így, 0 * 2^10 meg 0 * 2^20 még mindig csak 0 lesz :D

Bitek a pawnban
Mint tudjuk a mi kis pawnnunkban nincs nagyon típusosság, és minden változó 4 bájtot azaz 32 bitet foglal le magának ( Ebből jön, hogy a pawn egy 32 bites programozási nyelv. ). Azonban fontos lehet még megemlíteni, hogy ezek előjeles egész változók ( signed integers ) ami annyit takar, hogy minden változó fent tart 1 bitet a 32-ből ami jelöli, hogy pozitív vagy negatív szám ( Ezt a bitet szokták MSB-nek hívni ). Illetve azt is érdemes tudni, hogy a pawn 2-es komplementer rendszert használ, hogy előállítsa a negatív számokat, ez annyiból áll, hogy vesszük az egész, pozitív számot, majd minden bitjét kicseréljük az ellentétére és utána még hozzáadunk egyet, és meg is lenne a negatív szám. Példa:
Kód:
00000000000000000000000000000001  // 1
11111111111111111111111111111110 // Vesszük minden bit ellentétét
11111111111111111111111111111111 // hozzáadunk egyet, így megkaptuk a -1-t.


Operátorok, műveletek
Most pedig szépen nézzük végig mi áll rendelkezésünkre:

1. Bitenkénti ( bitek közötti ) ÉS
A bitenkénti ÉS művelet ( AND, & ) egy logikai operátor, ami csak akkor ad vissza 1-t , ha mindkét bit 1. Fontos, hogy nem egyezik meg a "&&" logikai operátorral.
Igazság táblázata ( 2 ábrázolás, kinek hogy... ):
Kód:
 & 0 1
 0 0 0
 1 0 1

Kód:
 A B A&B
 0 0  0
 1 0  0
 0 1  0
 1 1  1


Példa ( baloldalon bináris számrendszerben, ahogy a memóriában van, jobbon decimálisban ):
Kód:
 00000000000000000000000000001011  // 11
&00000000000000000000000000000111  // 7
=00000000000000000000000000000011  // 3


2. Bitenkénti ( bitek közötti ) VAGY
A bitenkénti VAGY művelet ( OR, | ) egy logikai operátor, ami mindig 1 -t ad vissza, kivéve, ha mindkét bit 0. Fontos, hogy nem összekeverendő a "||" logikai operátorral.
Igazság táblázata:
Kód:
 | 0 1
 0 0 1
 1 1 1

Kód:
 A B A|B
 0 0  0
 1 0  1
 0 1  1
 1 1  1


Példa:
Kód:
 00000000000000000000000000001011  // 11
|00000000000000000000000000000111  // 7
=00000000000000000000000000001111  // 15


3. Bitenkénti ( bitek közötti ) KIZÁRÓ VAGY
A bitenkénti KIZÁRÓ VAGY művelet ( XOR, ^ ) egy logikai operátor, ami mindig 1 -t ad vissza, ha különbözik a két bit.
Igazság táblázata:
Kód:
 ^ 0 1
 0 0 1
 1 1 0

Kód:
 A B A^B
 0 0  0
 1 0  1
 0 1  1
 1 1  0


Példa:
Kód:
 00000000000000000000000000001011  // 11
^00000000000000000000000000000111  // 7
=00000000000000000000000000001100  // 12


4. Bitenkénti ( bitek közötti ) NEGÁLÁS
A bitenkénti NEGÁLÁS ( NOT, ~ ) egy logikai operátor, ami eltér az előbbiektől, mivel 2 helyett csak 1 bitre alkalmazzuk. Az 1-kből 0-t a 0-kból 1-t csinál.
Igazság táblázata:
Kód:
A~A
0 1
1 0


Példa:
Kód:
~00000000000000000000000000001111 // 15
=11111111111111111111111111110000 // -16


5. Biteltolás ( shiftelés ) operátorok
A shift operátorok ( <<, >> ) a bitek tologatására szolgálnak. A << balra tol, a >> jobbra ( amerre mutatnak a nyilak ). Az operátor előtt ( bal oldalt ) szereplő szám az amit eltolunk, és az operátor után ( jobb oldalt ) lévő pedig, hogy mennyivel.

Jobbra tolás ( >> ):
Pozitív számmal:
Kód:
00000000000000000000000000001100 // 12
>> 2
00000000000000000000000000000011 // 3

Láthatjuk, hogy csak minden bit hátrébb került illetve az "üres" helyekre 0-k kerültek.
Negatív számmal:
Kód:
11111111111111111111111111111000 // -8
>> 2
11111111111111111111111111111110 // -2

Itt már látni, hogy szerepe van az MSB -nek, most 1-k kerültek az "üres" helyekre.

Balra tolás ( << ):
Pozitív számmal:
Kód:
00000000000000000000000000000100 // 4
<< 2
00000000000000000000000000010000 // 16

Ismét 0-kal egészül ki a szám, azonban itt már figyelni kell, ha túl sokáig shiftelünk egy pozitív számot akkor abból a túlcsordulás előtt ( Balról az első bit az MSB, ha az 1 lesz onnantól negatív a számunk. ) egy negatív szám lesz, túlcsordulásnál pedig a 0 -t veszi fel értékként.
Negatív számmal:
Kód:
11111111111111111111111111111000 // -8
<< 2
11111111111111111111111111100000 // -32

Láthatjuk, hogy itt megint balra shiftelésnél mindig 0-kal egészül ki a szám, legyen az pozitív vagy negatív. Azonban, ha túl sokat toljuk, akkor előfordulhat, hogy a szám elveszíti a negatív értéket és 0 lesz.

6. Logikai biteltolás ( logikai shiftelés ) operátor
A logikai shiftelésből csak egy létezik, mégpedig a jobbra logikai shiftelés ( >>> ). Sokban hasonlít a jobbra shiftelő operátorra ( >> ), azonban van egy fontos különbség.
Nézzük is példákkal:
Kód:
00000000000000000000000000010000 // 16
>>> 2
00000000000000000000000000000100 // 4

Itt még nem látni semmi különlegeset, ugyanaz, mint a jobbra shiftelés( >> ).

Negatív számmal:
Kód:
11111111111111111111111111111000 // -8
>>> 2
00111111111111111111111111111110 // 1073741822

Itt már látszik a különbség, logikai shiftelésnél nem számít az MSB értéke, mindig 0 kerül az üresedő helyekre, emiatt sose kaphatunk negatív eredményt.

Na, akkor itt lenne az elméleti rész vége.
Őszintén nekem a felhasználásukra amxmdox -en belül nincs más ötletem, csak, hogy logikai változók helyett használjunk bitműveleteket, így memóriát spórolva.
Hogyan lehetséges ez?
A bit műveletek segítségével tudjuk a változó bitjeit külön - külön kezelni, mint már említettem feljebb, és egy bit lehet 0 vagy 1, ergo egy változóban lehetőségünk van 32 igaz - hamis érték tárolására.
Egy példa kód, ha a játékos be van vakítva, és megöl közbe valakit kiírja, hogy "TE CSALOOO, WH-s!":
  1. #include < amxmodx >
  2.  
  3. new g_BitVakJatekos
  4. const TASK_VAKULAS_ID = 1000
  5.  
  6. public plugin_init()
  7. {
  8.     register_plugin( "TESZT", "1.0", "Akosch:." );
  9.  
  10.     register_event( "DeathMsg", "evHalal", "a" );
  11.     register_event( "ScreenFade", "evVakitas", "bef", "4=255", "5=255", "6=255", "7>199" );
  12. }
  13.  
  14. public evHalal( )
  15. {
  16.     new iGyilkos = read_data( 1 );
  17.     new iAldozat = read_data( 2 );
  18.  
  19.     if ( iGyilkos != iAldozat )
  20.         if ( g_BitVakJatekos & ( 1 << ( iGyilkos & 31 ) ) ) // Lekérés, h vak-e
  21.             client_print( iGyilkos, print_chat, "TE CSALOOO, WH-s!" );
  22. }
  23.  
  24. public evVakitas( iJatekos )
  25. {
  26.     g_BitVakJatekos |= ( 1 << ( iJatekos & 31 ) ); // "true"-ra állítás
  27.  
  28.     new Float:fVakulasIdeje = float( read_data( 2 ) / 4096 );
  29.    
  30.     set_task( fVakulasIdeje, "fnVakulasVege", TASK_VAKULAS_ID + iJatekos );
  31. }
  32.  
  33. fnVakulasVege( iId )
  34. {
  35.     iId -= TASK_VAKULAS_ID;
  36.    
  37.     g_BitVakJatekos &= ~( 1 << ( iId & 31 ) ); // "false"-ra állítás
  38. }


Felmerülhet sokakban a kérdés, hogy az 1 -t miért ( JátékosID & 31 )-el shifteljuk. Gondoljunk vissza kicsit, ha 32 biten 32-vel ( maximum játékos id ) tolnánk akkor az adatvesztéssel járna, kicsúszna a változóból amit bele akarunk tenni. Ezért van szükség egy kis trükre, nézzük csak mi lesz az eredménye a 32 & 31 -nek: 0. Miért jó ez nekünk? Mert a játékos azonosítók 1-től 32-ig tartanak, szóval a 0 szabad, és shiftelésnél se okoz gondot ( 1 << 0 = 1 ), szóval befér még a 32. játékos dolga is a változónkba.
Pár makró, apróság ehhez:
  1. //X helyére megy a játékos azonosítója, és iVar lesz a változó amibe tárolunk.
  2.  
  3. // Bekapcsolni ( igazra állítani )
  4. iVar |= ( 1 << ( X & 31 ) );
  5. // Kikapcsolni ( falsera állítani )
  6. iVar &= ~( 1 << ( X & 31 ) );
  7. // Átkapcsolni ( igazról hamisra, hamisról igazra )
  8. iVar ^= ( 1 << ( X & 31 ) );
  9. // Lekérni, hogy x -nek igaz v hamis
  10. iVar & ( 1 << ( X & 31 ) );
  11.  
  12. #define Bit_Set(%0,%1) %0 |= ( 1 << ( %1 & 31 ) )
  13. #define Bit_Clear(%0,%1) %0 &= ~( 1 << ( %1 & 31 ) )
  14. #define Bit_Toggle(%0,%1) %0 ^= ( 1 << ( %1 & 31 ) )
  15. #define Bit_Get(%0,%1) %0 & ( 1 << ( %1 & 31 ) )


Végül pedig szeretném megemlíteni, hogy honnan szedtem az infókat a tutoriálhoz:

Anthony - Bitműveletek, valamint gyakorlati alkalmazás a SA:MP-ban( főleg innen, nagyon szép összeszedett tut )
Bugsy - [TUT] Bits, Bit-fields, and Bit-wise Operators

Véleményeket várom, ha lenne valami jó ötletetek a használatukra akkor azt is szívesen látnám :D

_________________
Néha itt, de többször nem.

Ők köszönték meg Akosch:. nek ezt a hozzászólást (összesen 3):kiki (2015.12.23. 15:26) • mforce (2015.12.23. 16:16) • alfaanero (2015.12.23. 20:47)
  Népszerűség: 6.82%


Hozzászólás jelentése
Vissza a tetejére
   
Hozzászólások megjelenítése: Rendezés 
Új téma nyitása Hozzászólás a témához  [1 hozzászólás ] 


Ki van itt

Jelenlévő fórumozók: nincs regisztrált felhasználó valamint 0 vendég


Nyithatsz új témákat ebben a fórumban.
Válaszolhatsz egy témára ebben a fórumban.
Nem szerkesztheted a hozzászólásaidat ebben a fórumban.
Nem törölheted a hozzászólásaidat ebben a fórumban.
Nem küldhetsz csatolmányokat ebben a fórumban.

Keresés:
Ugrás:  
Powered by phpBB® Forum Software © phpBB Limited
Magyar fordítás © Magyar phpBB Közösség
Portal: Kiss Portal Extension © Michael O'Toole