Как да разбереме побитовите операции?
Здравейте,
от опеделено време насам се ровя в интернет пространството за теми, които касаят побитовите операции. Наистина попаднах на доста интересни теми, които показват всеки един оператор какво действие извършва, тяхното прилагане в компютрите и т.н.
Предполагам, че всеки човек знае смисъла от десетичните уравненията (20 - 5 = 15; 20 + 5 = 25; 20 / 5 = 4; 20 * 5 = 100; -5 + 20 = 15 и т.н.), защото прави аналогия с дадени предмети ( като 20 ябълки минус 5 ябълки е равно на 15 ябълки) и знае какво е значението за прилагането на такъв тип математически действия. Ако използвам същите числа в бинарен вариант с операторите за бинарно изчисление (0001 0100 (20) & 0000 0101 (5) = 0000 0100 (4); 0001 0100 (20) | 0000 0101 (5) = 0001 0101 (21); 0001 0100 (20) ^ 0000 0101 (5) = 0001 0001 (17); i т.н. с ' ~ ' оператор) идва и моят проблем, с каква цел го правя, какъв е смисъла от прилагането на тези операции и подобни изчисления, какво е значението на получените числа след действията или може ли да си направиме някаква аналогия в ежедневието си за да ги разбереме по - добре?
Надявам се да съм си задал въпроса правилно, пояснявам, че не става въпрос за как се изчисляват побитовите операции, а какво е приложението им и защо са ни нужни тяхните изчисления.
Поздрави,
Да, наистина доста интелигентно си го представил и ти благодаря за отделеното време. Може би просто ми е трудно да разбера нещо, което реално нямам ясна представа как мога да го приложа. Това е причината да отворя и тази тема, защот пресмятам битове намирам дадени стойности, които както обясни имат своето място, което същност аз търся. Най - вече по мое наблюдение не е и толкова лесно да ги разбереш, защото то е ясно, че 5+5=10, но 5 & 5 != 10 и точно това ме побърква, защото съм се научил да броя, но как да се науча и да "побитувам" ако мога да се изразя :D
Научил си се да броиш, но не си се научил да умножаваш трицифрени числа на ум, нали?
Ако не си крайно извратен, логично, едва ли ще "побитуваш" на ум, точно както е умножаваш трицифрени на ум.
По същият начин, по който пресмяташ трицифрени, така подхождай и тук - раздели си решението на малки стъпки.
1. Имаш десетично число, например 4.
2. Превръщаш го в двоична система. 4 делено на 2 има мода/остатък(%) 0, остават 2. Останалото 2 делено на 2 има мода 0, остава 1. Останалото едно делено на 2 има мода 1 и не остава нищо. Обръщаме го обратно и числото в двоична е 100. С много нули отпред според зависимост колко битово ни е цялочисленото, ако е int (Int32) -> още 29 нули. (00...00100)
3. Трябва на това число да смениш първия бит (от дясно на ляво, като се започва от нулев бит) на обратния бит на какъвто е в момента.
4. Как се променя бит? Имаме три оператора - OR, AND, XOR (|, &, ^). При OR, ако имаме поне един положителен бит, резултатът ще е положителен бит. При AND трябва и двата бита да са положителни (1) за да имам резултат с положителен бит. При XOR ако са различни, ще върне единица. Ако са еднакви ще върне 0. Т.е. ако битат в момента на тази позиция е 1 и го XOR-неш с 1 - ще върне 0. Ако битът е 0 и го XOR-неш с 1 ще върне 1. Т.е. трябва ти XOR, и то с единица, за да се промени бита. XOR с 0 ще остави битът същият. Което е супер, защото това означава че можем всички други битове да ги XOR-нем с нула и само този с единица, за да променим само него и запазим всички други.
5. Как да XOR-нем с единица само този бит? Ами това означава, че ни трябва число, което има на всички други позиции нулеви битове и само на 1ва позиция единичен бит (00...010). Принципно това число е 2, но нека работим по-абстрактно
6. Взимаме число, което на нулева позиция завършва на 1 и всички други битове са му нула (00...0001). Това число е 1
00 00 00 01
7. Местим всичките му битове наляво, толкова позиции, колкото е позицията, на която искаме да променим бита. Т.е. позиция 1. Всички битчета се местт една позиция наляво, а най-отляво ако се появяват нови битове това са 0 (ще ползваме bold за преместен бит и
зачеркванеза новодошъл бит). Операцията е едно (1) изместено на ляво (<<) един (1) път = 1 << 100 00 00 1
08. Нека поставим побитовата репрезентация на четири (4) на един ред и тази на новополученото ни число (1 << 1) на един ред под него
00 00 01 00 (4)
00 00 00 10 (1 << 1)
9. Нека извършим XOR между тези две числа. Това означава че бит по бит един под друг както са, ще се извърши XOR. Започваме от ней-десния бит (нулевия) наляво. Отгоре е 0 и отдолу е 0, XOR (0 ^ 0) = 0. Първият бит отгоре е 0, отдолу е 1, XOR (0 ^ 1) = 1. Вторият бит отгоре е 1, отдолу е 0, XOR (1 ^ 0) = 0. Третият бит, както и всички останали, отдолу са 0 и отгорре са нула, XOR (0 ^ 0) = 0. Какъв стана резултатът (болднатите числа от дясно на ляво)
00 00 01 10 демек (00...00110) = 6
10. Т.е. когато на четворката промениш битът на 1ва позиция на обратния на какъвто е бил се получава 6ца. Console.WriteLine(4 ^ (1 << 1)); Аналогично ако извършиш този XOR върху 6ца (новополученото число) ще върнеш тази 1ца на 0 и отново ще се получи 4ка.
Прилича ли ти на това как би сметнал 268 * 191? В смисъл такъв ако извадиш тетрадката и раздробиш това на малки стъпки пак ще имаш едни 10 основни :)