Подскажите, пожалуйста, почему мой ответ на "бумаге" не совпадает с компилятором интерпретатором. PHP: int a = -39; int b = a & 203; echo b; // 201 39 в двоичной системе будет 100 111. -39 => инвертировал в 011 000 и прибавил 1 => получил 011 001 (при проверке на онлайн calc не сходится) следовал этой инструкции (абзац отрицательные числа). Делаю побитовое AND: ( 1 и 1 дают единицу, все остальное 0) 203 в двоичной будет 1100 1011. 1100 1011 // 203 & 0001 1001 // -39 ________ 0000 1001 // не получается 201, как выдает echo Онлайн калькулятор говорит, что -39 это -100 111. Но, как тогда сделать побитовое AND ручками, на бумаге? Знак минуса смущает. 1100 1011 //203 & -10 0111 // -39 ________ ????????
Разрядность не учитываете. На современной машине у php-а (по крайней мере в линусе) 64 разряда на целое.
Это неправильно. Нужно инвертировать весь код в пределах заданной разрядности. Например, для 8-разрядной ячейки должно получиться 11 011 000. --- Добавлено --- Правильно смущает. Никакого знака минуса в памяти нет, если говорить о популярном представлении целых чисел, например -1 в восьми разрядах – это 255.
Ах, какая боль, 200 получается вместо 201. 1100 1011 // 203 & 1101 1000 // -39 ___________ 1100 1000 => 200 [10] [Updated] 1100 1011 // 203 & 1101 1001 // -39 (Нужно было прибавить единицу) ___________ 1100 1000 => 200 [10]
Ура! Спасибо! Получилось. А как компилятор узнал, и мне узнать, что 1101 1001 ( -39 ) это отрицательное число, ну и, если бы я переводил это число в десятичную с.с., то получил бы 217 (128 + 64 + 16 + 8 + 1)? Я читал, что знак определяет старший бит. Если отрицательное число, то 1, в противном случае 0. Но у 39 в двоичной системе старший бит, тоже 1.
минус типа первым битом идёт. поэтому либо с 0 по 255, либо -128 до +127. Ещё в каких-то архитектурах индейцы вступают в игру, но это редкость.
Никак. Дело только в трактовке. Если вам заранее сказать, что число имеет форму представления «целое со знаком» в восьми разрядах, то 217 вы никак не должны получить. Это просто признак, а не специально выделенный знаковый разряд. Кодирование таково, что у кодов отрицательных чисел этот бит всегда установлен (если числа считать отрицательными). Опять ошибаетесь, забывая про разрядность сетки. Нужно смотреть на полный дв. код: 00100111 P.S. Вообще это школьный материал. У меня племяши такое изучали.
Что за индейцы? В школе было такое пару занятий, но сдавал по принципу "сдал, забыл". А, сейчас, для игры понадобилось вытащить rgba из пикселя, но с пониманием что делаю. Там, есть такой момент: PHP: int rgba = -39; int red = (rgba >> 16) & 0xFF; И, непонятно, зачем делать & с 0xff, так как 0xFF это 1111 1111 и при побитовом AND результат останется тем же, т.е. (rgba >> 16). Т.е. чтобы компьютер перевел 8-разрядное 1101 1001 в -39 нужно сообщить ему, что необходимо рассматривать диапазон от -128 до +127, а не от 0 до 255?
точно, сорян в двоичной арифметике, отрицательных чисел не существует. Число 1101 1001 оно и в африке 1101 1001, а 217 или -39 это лишь представление в десятичной системе. Когда ты пишешь -39 в PHP, он воспринимает его как 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11011001. ВНЕЗАПНО, это число AND 11001011 (203) даёт то же самое 11001001 (201). Для записи отрицательного числа не просто старший бит устанавливается в 1. Возьмём число 6 в восьмибитном регисте, это 00000110, но 10000110 это не -6, а -122. Отрицательное 6 это 11111010. Оно выглядит как инвертированное положительное 5 (0000 0101). И так выглядят все отрицательные числа относительно положительных. -39 1 1 0 1 1 0 0 1 38 0 0 1 0 0 1 1 0 0000 0000 это самое маленькое число без знака (0). А 1000 0000 - это самое маленькое число со знаком, т.е. -128. С добавлением единиц, число увеличивается, пока не превратится в -1 или 11111111. Прибавлении единицы потребует нового разряда - 100000000 - но поскольку у нас всего 8 бит, то все единицы улетели за край и остался только 0. То есть это получилось само собой. Процессору не нужно как-то особо обозначать отрицательное число. Независимо от того, складывает пользователь, или вычитает, процессор только складывает.
Вымирающий вид. Всего-то? Вся команда выделяет значение третьего байта. Два младших байта сдвигаются в небытье. И & 0xFF чистит все, что остается выше младшего (после сдвига) байта.
В общем, кажется я разобрался. Для тех, кто в поисках ответа на свой вопрос в гугле в будущем найдет эту тему (в том числе и для меня): Одним из моих недопониманий было то, почему онлайн калькулятор при переводе из двоичной -> десятичную выдавал ВСЕГДА положительное число. Пример: 8-битный byte signed (в java нет типа unsigned) Возьмем число -2. В двоичном представлении 8-битном типе byte будет 1111 1110. Если ввести в онлайн калькуляторе 1111 1110, то получим не -2, а ну блин 254. Это скорее всего потому, что все вводимые в форму на сайте числа: приводятся к большему по диапазону типу, например, (тип byte) 1111 1110 приведется к (тип int) "24нуля и 1111 1110". Проще говоря, 8-битный signed приведется к 32-битному signed дописыванием спереди 24 нуля, соответственно новое десятичное число будет положительным; разбираются на цифры и приводятся в стиле: 1∙2^7+1∙2^6+1∙2^5+1∙2^4+1∙2^3+1∙2^2+1∙2^1+0∙2^0, что тоже всегда даст положительное число Из java переломным моментом в моем понимании стало вот этот мой эксперимент: PHP: // int var 1 = 24 нуля + 11111110 int var1 = Integer.parseInt("11111110",2); // понизили до 8 бит, т.е. 24 нуля убрали byte var2 = (byte)(Integer.parseInt("11111110",2)); System.out.println("int var1 = " + var1); // 254 System.out.println("byte var2 = " + var2); // -2 А, в примере с & 0xFF вообще просто теперь. 2 в int это 24 нуля + 0000 0010. -2 в int это 24 единицы + 1111 1110 Предположим, что -2 в двоичном виде это RGBA пикселя, тогда чтобы получить оттенок синего (последний байт) нужно : Код (Text): A | R | G | B 11111111 11111111 11111111 1111 1110 // -2 & 00000000 00000000 00000000 1111 1111 // 0xFF __________________________________ 00000000 00000000 00000000 1111 1110 // 254 почти полностью синий пиксель