Half-Life и Adrenaline Gamer форум http://aghl.ru/forum/ |
|
битование - "по здравому" FAQ http://aghl.ru/forum/viewtopic.php?f=39&t=703 |
Страница 1 из 1 |
Автор: | Turanga_Leela [ 19 мар 2012, 21:28 ] |
Заголовок сообщения: | битование - "по здравому" FAQ |
С перва не большое введение: Как известно компьютер в процессе своей работы оперирует лишь 2мя десятичными числами (или другими словами в двоичной системе счисления) 0/1 (истина/ложь). Понимая это - можно читать дальше Представление десятичных чисел в двоичном виде: Не залезая в с++ или иные высшие/низшие языки программирования, возьмем за стандарт pawn (по скольку именно он нас интересует и на данный момент работаем только с положительными значениями). В павне любая целочисленная переменная имеет 32 разряда (32 битные). Это значит что целочисленная переменная может содержать 32 bool значения. Что такое бит ? - это минимальный размер ячейки, возможные значения естественно - 0/1. Итак пример чисел: 1 - десятичное, это 1 в минус 31 степени число в двоичном представлении, дабы не писать 31 нолей перед единицей - допущу упращение записи "01"(не путать с 8 меричной системой счисления, о ней речь не идет) - ("1" - десятичное) Примеры Цитата: 1 = 01 В общем говоря переводы из 10й в 2ную(и наоборот) легко делаются в уме, исключения составляют лишь огромные значения на типо сотней тысяч ...2 = 010 3 = 011 4 = 0100 5 = 0101 ... Знаки побитовых операций Подробнее о логических операциях смотрите в других источниках, тут только освежение памяти Цитата: & - и (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 } } |
Автор: | Mr_ILYAS [ 30 сен 2013, 04:47 ] |
Заголовок сообщения: | Re: битование - "по здравому" FAQ |
Ничо не понятно 1) И что означает это так и не написали: new i |= 1 << (id - 1) 2) также не понятно: #define bit_owner_add(%1) i |= 1 << (%1 - 1) А именно что означает %1 ? 3) Еще не понятен оператор |= Я знаю операторы == != && || и другие. . . Но этот впервые вижу. Что он означает? Статья что есть, что ее нету. . . Написана для гуру. А для простых смертных как китайская грамота. |
Автор: | Lev [ 30 сен 2013, 10:32 ] |
Заголовок сообщения: | Re: битование - "по здравому" FAQ |
Это как бы базовые знания. Получить их можно почитав какую-нибудь книжку по программированию, хотя бы даже на Си. Обозначения: 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 - дефайн - определяет какой текст на какой заменить. Их можно объединять через "или": Код: keys |= MENU_KEY_1 | MENU_KEY_2 Оператор |= имеет смысл: Код: keys = keys | MENU_KEY_1 | MENU_KEY_2Т.е. значение в переменной сначала объединяется через "или", а потом засовывается обратно. +=, -=, /=, *= - это всё тоже самое, считать переменную назначения участником операции, только операции разные. %1 в дефайне - это способ передать параметры в дефайн. Если есть: Код: #define abc(%1) xyz(%1 + 1)То код: Код: new i;после обработки препроцессором примет вид: Код: new i; |
Автор: | Mr_ILYAS [ 30 сен 2013, 23:27 ] |
Заголовок сообщения: | Re: битование - "по здравому" FAQ |
Извини, дружище, но не быть тебе учителем)) Я уже давно во всём этом разобрался. Но прочитав тебя я всё равно ничего не понял. Вот http://ziggi.org/pawn-pobitovye-operatory/тут материал куда лучше изложен) Кстати вот то, что получилось в итоге моих знаний. viewtopic.php?f=38&t=1453&p=17366#p17366 |
Страница 1 из 1 | Часовой пояс: UTC + 5 часов [ Летнее время ] |
Powered by phpBB® Forum Software © phpBB Group https://www.phpbb.com/ |