Русское сообщество по скриптингу

Работа с битами (использование операторов)

Статьи или фрагменты кода для новичков и уже опытных скриптеров по AMXX.

Модератор: Chuvi

Правила форума
1. Запрещено материться и оскорблять других участников форума.
2. Запрещен флуд, оффтоп, дабл постинг во всех разделах форума, кроме раздела "Болтовня".
3. Запрещено взламывать сайт/форум или наносить любой вред проекту.
4. Запрещено рекламировать другие ресурсы.
5. Запрещено создавать темы без информативного названия. Название темы должно отображать ее смысл.

В данном разделе форума разрешено создавать темы, касающие только обучающему материалу по AMX Mod X.

Работа с битами (использование операторов)

Сообщение DJ_WEST » 07 окт 2009, 11:32

Автор: ot_207
Перевод и редактирование: DJ_WEST

Данная статья поможет вам научиться работать с битами через битовые операторы, что даст вам некоторый прирост работы плагина по сравнению с булевыми массивами. Работа с битами быстрее для компьютера, но для понимания кода человеком сложнее.

Что такое битсумма?
Битсумма - это то, на чем основана работа памяти. Память состоит из ячеек (битов), которые могут хранить два значения: 1 и 0. Пример, как хранится число в одном байте (байт = 8 бит):
"8" (обычное число) = "00001000" (число в памяти [1 байт])


Как битсумма работает?
Идея состоит в том, что битсумма позволяет управлять ее позицией. И мы можем проверить имеет ли позиция 1 или 0.

Какие есть операторы и как они работают?
  • Оператор |
    Данный оператор работает, как логический оператор ||, но производит операцию над каждым битом.
    Пример:
    Код: Выделить всё
    first_byte = "10010001" 
    second_byte 
    = "01010001"

    first_byte | second_byte = "11010001"  

    Код: Выделить всё

    |     1      0
    1     1      1
    0     1      0

  • Оператор &
    Данный оператор работает, как логический оператор &&, но производит операцию над каждым битом.
    Пример:
    Код: Выделить всё

    first_byte 
    = "10010001" 
    second_byte 
    = "01010001" 

    first_byte 
    & second_byte = "00010001" 
     

    Код: Выделить всё
    &     1      0
    1     1      0
    0     0      0

  • Оператор ^ (Исключающее ИЛИ)
    Данный оператор работает, как логический оператор ^^, но производит операцию над каждым битом.
    Пример:
    Код: Выделить всё

    first_byte 
    = "10010001" 
    second_byte 
    = "01010001" 

    first_byte 
    ^ second_byte = "11000000" 
     

    Код: Выделить всё

    ^    1      0
    1    0      1
    0    1      0

  • Оператор ~
    Данный оператор отрицает каждый бит, поэтому бит 0 становится 1, а бит 1 становится 0.
    Пример:
    Код: Выделить всё

    first_byte 
    = "10010001" 

    ~first_byte = "01101110" 
     

    Код: Выделить всё

    ~1 = 0
    ~0 = 1

  • Оператор <<
    Данный оператор смещает биты влево на указанное число позиций.
    Например:
    Код: Выделить всё
    "00001100" << 1 = "00011000"  

    Если мы преобразуем полученное число в десятичную систему, то увидем, что в результате получилось число умноженное на 2. Следовательно, 1<<3 будет тоже самое, что 2^3 * 1.
  • Оператор >>
    Данный оператор смещает биты вправо на указанное число позиций.
    Например:
    Код: Выделить всё
    "00000111" >> 3 = "00000000" 
     

Как работают обычные числа?
Числа хранятся в ячейках. Следовательно, числа из десятичной системы преобразуются в двоичную. К примеру, число 9 становится "00001001". Чтобы перобразовать число из двоичной системы в десятичную, нам нужно умножить каждую позицию на число 2 в степени:
00001001: 1*(2^0) + 0*(2^1) + 0*(2^2) + 1*(2^3) + 0*(2^4) + 0*(2^5) + 0*(2^6) + 0*(2^7) = 1 + 8 = 9

Как применить данную статью в моих плагинах?
Мы можем использовать битсуммы вместо булевых массивов.
Примечание: Важно отметить, что если, к примеру, у нас есть 1 = 0000 0000 0000 0000 0000 0000 0000 0001 и выполняя 1 << 32 мы получаем: 1 0000 0000 0000 0000 0000 0000 0000 0000, как видно 1 выходит за пределы. Поэтому при 32 игроках на сервере, мы не получим верную работоспособность. Для этого надо отнять 1. Вместо 1-32 у нас будет 0-31.

К примеру, вместо:
Код: Выделить всё

new bool
: is_alive[33] 
 

Запишем:
Код: Выделить всё

new bitsum_is_alive 


Вместо:
Код: Выделить всё

if 
(is_alive[id]) 
{ 
} 
 

Запишем:
Код: Выделить всё

if 
(bistum_is_alive & (1<<(id-1))) 
{ 
} 
 


Вместо:
Код: Выделить всё
is_alive[id] = true

Код: Выделить всё
is_alive[id] = false

Запишем:
Код: Выделить всё
bitsum_is_alive |= (1<<(id-1)) 

Код: Выделить всё
bitsum_is_alive &=  ~(1<<(id-1)) 


Если рассматривать, к примеру, присвоение:
Код: Выделить всё
is_alive[id] = true

или как мы заменили:
Код: Выделить всё
bitsum_is_alive |= (1<<(id-1)) 

где id = 1 при bitsum_is_alive = 0000 0000 0000 0000 0000 0000 0000 0000, то есть игрок id = 1, первый на сервере.
Вычисления:
Код: Выделить всё

1. id
-= 1-= 0
2. 1
<<(id-1) = 1 << 0 =
0000 0000 0000 0000 0000 0000 0000 0001 << 0 = 0000 0000 0000 0000 0000 0000 0000 0001
3. bitsum_is_alive 
| (1<<(id-1)) = 
0000 0000 0000 0000 0000 0000 0000 0000
|
0000 0000 0000 0000 0000 0000 0000 0001
=
0000 0000 0000 0000 0000 0000 0000 0001
4. bitsum_is_alive 
= bitsum_is_alive | (1<<(id-1)) = 0000 0000 0000 0000 0000 0000 0000 0001


А если допустить, к примеру, что bitsum_is_alive = 0000 0000 0000 0010 0100 0000 0100 0001, что говорит нам о том, что игроки у которых id равно 1, 7, 15, 18 - живы, так как у них бит равен 1, отсчет битов ведется с конца. То присвоение игроку id = 7 (выделенный красный бит) статуса мертвый (бит в 0), будет происходить след. образом (как мы заменяли код выше):
Код: Выделить всё
bitsum_is_alive &=  ~(1<<(id-1)) 

Вычисления:
Код: Выделить всё

1. id
-= 7-= 6
2. 1
<<(id-1) = 1<<=
0000 0000 0000 0000 0000 0000 0000 0001 << 6 = 0000 0000 0000 0000 0000 0000 0100 0000
3. 
~(1<<(id-1)) = 1111 1111 1111 1111 1111 1111 1011 1111
4. bitsum_is_alive 
& ~(1<<(id-1)) = 
0000 0000 0000 0010 0100 0000 0100 0001
&
1111 1111 1111 1111 1111 1111 1011 1111
=
0000 0000 0000 0010 0100 0000 0000 0001
5. bitsum_is_alive 
= bitsum_is_alive & ~(1<<(id-1)) = 0000 0000 0000 0010 0100 0000 0000 0001. 

Мы получили bitsum_is_alive = 0000 0000 0000 0010 0100 0000 0000 0001

Можно ли как-то оптимизировать работу?
Можно сделать stock функцию:
Код: Выделить всё

stock is_user_alive
(id) 
{ 
      return 
(bistum_is_alive & (1<<(id-1))) ? 1 : 0 
} 
 

Или макрос:
Код: Выделить всё
#define is_user_alive(%1) (bistum_is_alive & (1 << (%1-1))) ? 1 : 0 
 
Не пишите мне в ЛС: если вам нужна помощь на бесплатной основе. Любые вопросы на форум.
Аватара пользователя
DJ_WEST
Администратор
 
Сообщения: 3641
Зарегистрирован: 22 авг 2009, 00:38
Благодарил (а): 48 раз.
Поблагодарили: 2209 раз.
Опыт программирования: Больше трех лет
Языки программирования: Counter-Strike 1.6
Counter-Strike: Source
Left 4 Dead
Left 4 Dead 2

Re: Работа с битами (использование операторов)

Сообщение Fedcomp » 07 окт 2009, 17:43

Помоему это довольно сложно, даже оочень сложно
Не помогаю в ЛС - есть форум.
Плагины тоже не пишу, на форуме достаточно хороших скриптеров.


"я ставлю зависимости потому что мне приятно" - subb98 @ 2017
Аватара пользователя
Fedcomp
Администратор
 
Сообщения: 4936
Зарегистрирован: 28 авг 2009, 20:47
Благодарил (а): 813 раз.
Поблагодарили: 1317 раз.
Языки программирования: =>
pawn / php / python / ruby
javascript / rust

Re: Работа с битами (использование операторов)

Сообщение DJ_WEST » 07 окт 2009, 23:14

Fedcomp, это кажется на первый взгляд. Я итак попытался наиболее легко передать =)
Не пишите мне в ЛС: если вам нужна помощь на бесплатной основе. Любые вопросы на форум.
Аватара пользователя
DJ_WEST
Администратор
 
Сообщения: 3641
Зарегистрирован: 22 авг 2009, 00:38
Благодарил (а): 48 раз.
Поблагодарили: 2209 раз.
Опыт программирования: Больше трех лет
Языки программирования: Counter-Strike 1.6
Counter-Strike: Source
Left 4 Dead
Left 4 Dead 2

Re: Работа с битами (использование операторов)

Сообщение WC-HUMMER » 23 ноя 2009, 23:04

DJ_WEST, Ну ты мозг))) гдн ты такой нашёлся...
а ты закончил какоето учебное завидение или всему учился сам ?
Аватара пользователя
WC-HUMMER
 
Сообщения: 2
Зарегистрирован: 20 ноя 2009, 21:53
Благодарил (а): 1 раз.
Поблагодарили: 1 раз.
Языки программирования: Counter-Strike 1.6

Re: Работа с битами (использование операторов)

Сообщение Fedcomp » 24 ноя 2009, 01:25

DJ_WEST писал(а):Fedcomp, это кажется на первый взгляд. Я итак попытался наиболее легко передать =)

Проблема в дальнейшей читаемости кода))
я помню паскаль вообще китайской грамотой был, но очень быстро разобрался ...
теперь и на павн/сурс павн пытаюсь также
WC-HUMMER писал(а):DJ_WEST, Ну ты мозг))) гдн ты такой нашёлся...
а ты закончил какоето учебное завидение или всему учился сам ?

Ты знаешь PAWN учебные заведения? :-D :thumbs_up
а вообще опыт нарабатывается только практикой
Не помогаю в ЛС - есть форум.
Плагины тоже не пишу, на форуме достаточно хороших скриптеров.


"я ставлю зависимости потому что мне приятно" - subb98 @ 2017
Аватара пользователя
Fedcomp
Администратор
 
Сообщения: 4936
Зарегистрирован: 28 авг 2009, 20:47
Благодарил (а): 813 раз.
Поблагодарили: 1317 раз.
Языки программирования: =>
pawn / php / python / ruby
javascript / rust

Re: Работа с битами (использование операторов)

Сообщение DJ_WEST » 24 ноя 2009, 10:10

а ты закончил какоето учебное завидение или всему учился сам ?

Ага, Гарвардский университет, факультет по Pawn'у xD Самому пришлось, когда нужно было для начала редактировать и писать маленькие плагины для сервера.
Не пишите мне в ЛС: если вам нужна помощь на бесплатной основе. Любые вопросы на форум.
Аватара пользователя
DJ_WEST
Администратор
 
Сообщения: 3641
Зарегистрирован: 22 авг 2009, 00:38
Благодарил (а): 48 раз.
Поблагодарили: 2209 раз.
Опыт программирования: Больше трех лет
Языки программирования: Counter-Strike 1.6
Counter-Strike: Source
Left 4 Dead
Left 4 Dead 2

Re: Работа с битами (использование операторов)

Сообщение Ser_UFL » 24 ноя 2009, 15:10

и писать маленькие плагины для сервера.

Ага, такие как RHLG...
Гарвардский университет, факультет по Pawn'у

Предлагаю открыть платные курсы по Pawn-у ! Виталь, желаешь заняться преподавательской деятельностью? ))
Запомните, всегда по жизни вас будут красить вежливость и спокойствие, а не наезды и дешевые понты ;)
Аватара пользователя
Ser_UFL
 
Сообщения: 975
Зарегистрирован: 22 авг 2009, 19:30
Откуда: Hell
Благодарил (а): 276 раз.
Поблагодарили: 380 раз.
Языки программирования: Counter-Strike 1.6:
WebMod-scripts, little Pawn.

Re: Работа с битами (использование операторов)

Сообщение DJ_WEST » 24 ноя 2009, 19:05

Ага, такие как RHLG...

Ну, если вспомнить первые версии RHLG...
Предлагаю открыть платные курсы по Pawn-у ! Виталь, желаешь заняться преподавательской деятельностью? ))

Вот преподом никогда не мечтал стать xD
Не пишите мне в ЛС: если вам нужна помощь на бесплатной основе. Любые вопросы на форум.
Аватара пользователя
DJ_WEST
Администратор
 
Сообщения: 3641
Зарегистрирован: 22 авг 2009, 00:38
Благодарил (а): 48 раз.
Поблагодарили: 2209 раз.
Опыт программирования: Больше трех лет
Языки программирования: Counter-Strike 1.6
Counter-Strike: Source
Left 4 Dead
Left 4 Dead 2

Re: Работа с битами (использование операторов)

Сообщение Zefir » 09 янв 2010, 14:10

Чтобы правильно задать вопрос, нужно знать более половины ответа...
Cerberus - замена amxbans и многому другому
Аватара пользователя
Zefir
 
Сообщения: 21
Зарегистрирован: 31 авг 2009, 21:06
Откуда: Kiev
Благодарил (а): 2 раз.
Поблагодарили: 13 раз.
Опыт программирования: Больше трех лет
Языки программирования: Counter-Strike 1.6

Re: Работа с битами (использование операторов)

Сообщение kalash1k » 08 ноя 2010, 22:47

Неплохо было бы ещё привести примеры таких преобразований на каком-нибудь простеньком плагине, где используется и is_user_alive и булевые значения ну и т.п.

Аватара пользователя
kalash1k
 
Сообщения: 210
Зарегистрирован: 17 янв 2010, 14:08
Откуда: СССР
Благодарил (а): 15 раз.
Поблагодарили: 20 раз.
Опыт программирования: Больше трех лет
Языки программирования: Counter-Strike 1.6

След.

Вернуться в Статьи / фрагменты кода

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 9