Half-Life и Adrenaline Gamer форум

Всё об игре в Халф-Лайф и АГ
Текущее время: 29 мар 2024, 04:11

Часовой пояс: UTC + 5 часов [ Летнее время ]




Начать новую тему Ответить на тему  [ Сообщений: 4 ] 
Автор Сообщение
 Заголовок сообщения: битование - "по здравому" FAQ
СообщениеДобавлено: 19 мар 2012, 21:28 
Не в сети
Аватара пользователя
Зарегистрирован:
24 янв 2011, 03:32
Последнее посещение:
09 дек 2021, 03:04
Сообщения: 756
Откуда: Futurama
С перва не большое введение: Как известно компьютер в процессе своей работы оперирует лишь 2мя десятичными числами (или другими словами в двоичной системе счисления) 0/1 (истина/ложь). Понимая это - можно читать дальше :)

Представление десятичных чисел в двоичном виде:
Не залезая в с++ или иные высшие/низшие языки программирования, возьмем за стандарт pawn (по скольку именно он нас интересует и на данный момент работаем только с положительными значениями). В павне любая целочисленная переменная имеет 32 разряда (32 битные). Это значит что целочисленная переменная может содержать 32 bool значения. Что такое бит ? - это минимальный размер ячейки, возможные значения естественно - 0/1. Итак пример чисел:
1 - десятичное, это 1 в минус 31 степени число в двоичном представлении, дабы не писать 31 нолей перед единицей - допущу упращение записи "01"(не путать с 8 меричной системой счисления, о ней речь не идет) - ("1" - десятичное)

Примеры
Цитата:
1 = 01
2 = 010
3 = 011
4 = 0100
5 = 0101 ...
В общем говоря переводы из 10й в 2ную(и наоборот) легко делаются в уме, исключения составляют лишь огромные значения на типо сотней тысяч ...

Знаки побитовых операций
Подробнее о логических операциях смотрите в других источниках, тут только освежение памяти :)

Цитата:
& - и (true - только при совпадении true разрядов или другими словами при совпадении "1")
011 001 010 // 202
&
110 011 000 // 408
=
010 001 000 // 136

~ - не (побитовое отрицание)
~001 101 010 = 110 010 101

| - или
010 111 101
|
001 100 001
=
011 111 101

^ - исключающие или (либо)
111 000 111
^
010 110 011
=
101 110 100

Операции смещений
<< - Побитовое смещение влево на указанное колличество разрядов (Другими словами умножение на 2, при попытке умножения применять нужно разумно!)
>> - Побитовое смещение вправо на указанное колличество разрядов (Другими словами деление на 2, при попытке деления применять нужно разумно!)

Принцип записи в переменную
new i |= 1 << (id - 1) // id - индекс игрока, операция "- 1" уменьшение на еденицу - нужно для того что бы не выйти за пределы переменной i, к примеру при значении id = 32 именно это и должно произойти, но на деле этого не происходит и при превышении разрядов - запускается 2й круг. Вычитание по сути является действием по желанию, лично я его применяю

Для удобочитаемости и применения данных методов - рекомендую использовать макросы (О них смотрите в других источниках)

#define bit_owner_add(%1) i |= 1 << (%1 - 1)
#define bit_owner_sub(%1) i &= ~(1 << (%1 - 1))
#define bit_owner(%1) i & 1 << (%1 - 1)

В итоге имеем 3 "функции"(-_-): записи, чтения, удаления bool значений

Пример использования:
Цитата:
new g_connected

#define bit_connected_add(%1) g_connected |= 1 << (%1 - 1)
#define bit_connected_sub(%1) g_connected &= ~(1 << (%1 - 1))
#define bit_connected(%1) g_connected & 1 << (%1 - 1)

public client_connected(id)
{
bit_connected_add(id)
}

public client_disconnect(id)
{
bit_connected_sub(id)
}

function()
{
for(new i = 1; i <= g_maxplayers; i++)
{
if(bit_connected(i)) // альтернатива функции - is_user_connected()
{
// code
}
}
}
По аналогии можно выполнить любые булевые проверки, к примеру проверку на жизнь игрока.

Немного фичей:
Цитата:
1)
Можно используя - ^ выполнить проверку "!="
if(killer ^ victim) // Так-же можно сравнивать любые другие числа
{
// Выполнится только если убийца НЕ жертва, причем индексы могут быть больше "32"
}

2)
Можно так-же применить проверку булевого значения методом отрицания псевдо массива (методом "отпротивного"). Иногда именно такой метод приходиться применять для оптимизации кода :)
if(1 << (id - 1) & ~g_connected) // вернет true - если игрока нету, иначе если он есть вернет - false

3)
Метод применения "исключающего или"(либо)
if(g_Flags & flag_Server) // Если такой флаг есть
{
g_Flags ^= flag_Server // Этой манипуляцией мы исключим флаг, НО если применить подобные метод без проверки на наличие флага - флаг наоборот присвоится. Получается закономерность - если значения НЕТУ - оно присвоится и наоборот - если есть - УНИЧТОЖИТСЯ!. Хотелось бы еще отметить, что это применимо только к побитовым операциям, обычные десятичные числа так лучше не складывать или вычитать, по-скольку последствия будут не предсказуемыми!

// Безопасным методом исключения флага является этот - g_Flags &= ~flag_Server , его можно применять без проверок наличия флага, если флага нету ничего не произойдет
}

4)
Превосходство флагов и побитовых операций(Особенно сильный эффект при проверке 2х и более флагов), так к примеру можно выполнить подобные сравнения:

#define _ADMIN_FLAGS (ADMIN_IMMUNITY | ADMIN_RESERVATION) // Возможно так-же сравнение флагов энтити - родных или тех которые содержаться в ваших переменных

if(!(((get_user_flags(id) & _ADMIN_FLAGS) ^ _ADMIN_FLAGS)))
{
// юзер обязательно должен иметь 2 этих флага
}

if(get_user_flags(id) & _ADMIN_FLAGS)
{
// Юзер должен иметь хотябы 1н флаг из перечня или некоторые из них или все флаги
}

5)
Возможность обьединения разных систем счислений
set_pev(beam, pev_rendermode, (pev(beam, pev_rendermode) & 0xF0) | 1 & 0x0F)

6)
Одной из важнейших особенностей подобных проверок является то, что - хоть переменные и содержат по сути булевые значения, они (значения) являются целочисленными. Это позволяет производить манипуляции с функцией - switch

switch(g_Flags & flag_Server)
{
case 0:
{
// false - флага нету
}
default:
{
// true - флаг есть
}
}

Еще пример:

switch(1 << (id - 1) & ~g_connected) // вспоминаем что происходит при отрицании псевдо-массива
{
case 0:
{
// true
}
default:
{
// false
}
}


Вернуться к началу
 Профиль 
  
 Заголовок сообщения: Re: битование - "по здравому" FAQ
СообщениеДобавлено: 30 сен 2013, 04:47 
Не в сети
Зарегистрирован:
26 сен 2013, 07:26
Последнее посещение:
07 окт 2013, 18:42
Сообщения: 25
Ничо не понятно

1)
И что означает это так и не написали:
new i |= 1 << (id - 1)

2)
также не понятно:
#define bit_owner_add(%1) i |= 1 << (%1 - 1)
А именно что означает %1 ?

3)
Еще не понятен оператор |=
Я знаю операторы == != && || и другие. . .
Но этот впервые вижу. Что он означает?

Статья что есть, что ее нету. . . Написана для гуру. А для простых смертных как китайская грамота.


Вернуться к началу
 Профиль 
  
 Заголовок сообщения: Re: битование - "по здравому" FAQ
СообщениеДобавлено: 30 сен 2013, 10:32 
Не в сети
Site Admin
Зарегистрирован:
01 июн 2010, 01:27
Последнее посещение:
26 мар 2024, 21:42
Сообщения: 6864
Это как бы базовые знания. Получить их можно почитав какую-нибудь книжку по программированию, хотя бы даже на Си.
Обозначения: b - двоичное число, d - десятичное, h - шестнадцатиричное

Сдвигаем влево:
1 << 0 = 0001b = 1d
1 << 1 = 0010b = 2d
1 << 2 = 0100b = 4d

Операция "или":
(1 << 0) | (1 << 2) = 0001b | 0100b = 0101b = 5d
Установленный бит говорит что кнопка меню активна.

Для кнопок есть дефайны MENU_KEY_0 ... MENU_KEY_9
Код:
#define MENU_KEY_1      (1<<0)
#define MENU_KEY_2      (1<<1)

#define - дефайн - определяет какой текст на какой заменить.

Их можно объединять через "или":
Код:
keys |= MENU_KEY_1 | MENU_KEY_2

Оператор |= имеет смысл:
Код:
keys = keys | MENU_KEY_1 | MENU_KEY_2
Т.е. значение в переменной сначала объединяется через "или", а потом засовывается обратно.
+=, -=, /=, *= - это всё тоже самое, считать переменную назначения участником операции, только операции разные.

%1 в дефайне - это способ передать параметры в дефайн.
Если есть:
Код:
#define abc(%1) xyz(%1 + 1)
То код:
Код:
new i;
if (abc(i))
после обработки препроцессором примет вид:
Код:
new i;
if (xyz(i + 1))


Вернуться к началу
 Профиль 
  
 Заголовок сообщения: Re: битование - "по здравому" FAQ
СообщениеДобавлено: 30 сен 2013, 23:27 
Не в сети
Зарегистрирован:
26 сен 2013, 07:26
Последнее посещение:
07 окт 2013, 18:42
Сообщения: 25
Извини, дружище, но не быть тебе учителем))

Я уже давно во всём этом разобрался. Но прочитав тебя я всё равно ничего не понял.

Вот http://ziggi.org/pawn-pobitovye-operatory/тут материал куда лучше изложен)

Кстати вот то, что получилось в итоге моих знаний.
viewtopic.php?f=38&t=1453&p=17366#p17366


Вернуться к началу
 Профиль 
  
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 4 ] 

Часовой пояс: UTC + 5 часов [ Летнее время ]


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

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


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  
Создано на основе phpBB® Forum Software © phpBB Group
Русская поддержка phpBB