Форум Flasher.ru
Ближайшие курсы в Школе RealTime
Список интенсивных курсов: [см.]  
  
Специальные предложения: [см.]  
  
 
Регистрация Блоги Правила Справка Пользователи Календарь Поиск рулит! Сообщения за день Все разделы прочитаны
 

Вернуться   Форум Flasher.ru > Блоги > Psycho Tiger

Рейтинг: 5.00. Голосов: 8.

Поговорим о битах

Запись от Psycho Tiger размещена 30.08.2010 в 14:33
Обновил(-а) Psycho Tiger 05.12.2010 в 14:23

Люди начинают спрашивать меня, читая мои записи в блоге - а что это такое "<<" или "&", как оно работает и вообще зачем оно нужно. Сегодня я вам об этом и расскажу.
Статья рассчитана на подрастающих девелоперов, ничего революционного в ней нет =)

Итак, что же творится behind the magic =)

Начнём с простого, вообще поймём, что же такое биты.

Есть байты. Байт - это 8 битов. А бит - это элемент, который может принимать значения 0 или 1. То есть байт - это восемь положений 0 или 1. (прошу прощения за мой очень вольный рассказ). Компьютер вообще работает с двоичной системой счисления, то есть у него есть только цифры 0 и 1. У нас их целых десять - 0,1,2,3,4..9. Поэтому привычная система исчисления для нас десятичная. И вот же проблема: компьютер использует двоичную, а мы привыкли использовать десятичную, как же нам... Да всё нормально, успокойтесь. Сущность числа не меняется от записи его в любой из систем исчисления.
Например, записав во флеше в шестандцатиричной системе 0xFF мы записали число 255. Поэтому делая trace(0xFFFFFF) мы видим какое то странно число, начинающиеся с 16.... Дело в том, что флеш специально выводит нам числа в десятичной системе, как нам удобно. А теперь давайте запишем какое-нибудь число, например "2" в двоичной системе, "родной" для компьютера:

10

Но каждый разряд принимает значения или 0, или 1. Это значит что каждый разряд - это бит. Но чаще люди записывают все 8 разрядов сразу, чтобы видеть тот самый байт.

00000010

Вот он байт. Таким байтом записано число 2 в компьютерном представлении. Конечно, оперировать с битами должно быть куда быстрее - мы будем отдавать компьютеру приказы в его "родной среде", поэтому важно понимать, как они работают и что делают.
Сейчас рассмотрим 3 оператора: |, & и >>, а потом посмотрим что же это дело делает на практике.

Оператор |: это оператор бинарного или. Он сравнивает каждый бит первого байта с соответствующим каждым битом второго байта, и если хотя бы один из них равен единице - на выходе будет единица.
Пример:
2 | 3 = 3
00000010 | 00000011 = 00000011

Важно! Первый бит идёт справа.

Сравниваем первый бит с первым битом: 0 | 1 = 1, т.к. хотя бы один из них равен единице.
Сравниваем второй бит с вторым битом: 1 | 1 = 1, т.к. хотя бы один из них равен единице.
Остальные биты: 0 | 0 = 0, т.к. ни один бит не равен единице.


Оператор &: это оператор бинарного и. Делает то же самое, что и "или", только чтобы на выходе была единица нужно чтобы оба бита были равны единице.
Пример:
2 & 3 = 2
00000010 & 00000011 = 00000010
Сравниваем первый бит с первым битом: 0 & 1 = 0, т.к. оба бита НЕ равны 1.
Сравниваем второй бит со вторым: 1 & 1 = 1, т.к. оба бита равны 1
Остальные: 0 & 0, т.к. оба бита не равны 1.

Оператор >>: это оператор сдвига вправо. Он сдвигает биты. Второй операнд - это на сколько битов нужно сдвинуть это число.
Например:
00001100 >> 1 = 00000110
Мы просто подвинули число целиком на бит вправо, а слева вдвинули ноль. Ещё пример:
11100000 >> 2 = 00111000
Мы сдвинули это число 2 раза вправо, а слева добавили 2 нуля.

Важно понять, что при сдвиге вправо разряды, которые "выбились" уходят в небытие и их уже никак не вернуть.
Например:
00000111 >> 2 = 00000001


Оператор << работает аналогично, но "вдвигает" нули справа, при этом количество байт, отводящиеся под это число может увеличиться.
UPD: я вот прочитал это и не знаю под каким веществом писал эту статью. Во флеше для целых чисел есть только int и uint, причем они оба всегда по 4 байта (32 бита). Что я имел ввиду под количеством "новых" байт останется для меня загадкой.
Например:
11000000 << 2 = 00000011 00000000

Мы подвинули число 2 раза влево, вдвинув нули справа, но из за этого число не смогло поместиться в 8 бит и ему был отведен ещё один байт. Максимальное число, которое можно "всунуть" байт - это 255 (11111111).

А вот теперь самое вкусное. Как это можно применить на практике?
Но сперва поправка: всё нижеописанное будет иметь место при работе с целыми положительными числами.

Наверное, вы уже задумались над тем, что если бит - это 0 или 1, то есть false или true - то можно передать 8 логических значений за один байт! Остался вопрос, как это сделать приятным для использования. А очень просто: у нас есть оператор |. И если мы заведем константы с числами "00000001", "00000010", "00000100" и т.д., то объединяя их мы можем получать комбинации для передачи этих самых 8 значений одним числом.
В итоге каждое число, от 0 до 255 будет занято какой-то одной уникальной комбинацией этих 8 флагов.
Ради примера сделаем что нужно передать 3 логических значения: горит ли первая лампочка, вторая и третья. Каждая из них может гореть вне зависимости, горит ли какая-то другая.
Сейчас для краткости записи я буду писать только первые 3 разряда, т.е. число 00000111 я буду записывать как 111.
Что делаем:
Заводим константы со значениями 001, 010, 100. В AS3 убрали возможность записывать число в двоичном виде, поэтому используя калкулятор записываем их в десятичном:
Код:
const b1 = 1
const b2 = 2
const b3 = 4
Кстати говоря, когда только один бит в числе равен единице - это какая то степень двойки, равная номеру биту по счету, начиная с 0.

Теперь, чтобы задать что горит, например, первая лампочка и третья нужно передать число 101. Его можно записать вот так: "100 | 001", то есть, проще говоря b1 | b3.
Вот и всё. Мы передали уникальное число, которое соответствует комбинации первой и третьей лампочки включенной, и выключенной второй. Осталось это дело только распознать там, куда мы это передали.

А распознаётся это дело с помощью оператора &. Это битовая маска, так сказать.
Наложить её очень просто: нужно просто понять, где нам нужно видеть биты, а где не нужно. Например, чтобы понять, включена ли первая лампочка нужно наложить на это переданное число маску "001" и посмотреть на результат. Второй и третий бит будут равны 0, т.к. оператор "и" их не пропустит, а результат от первой лампочки будет целиком зависеть от переданного числа: если первый бит у него 1 - результатом будет 1, если второй бит 0, то результатом будет 0.
Со второй лампочкой аналогично, накладывая маску 010 - если лампочка не горит, значит результат будет 0, если горит - результат будет 010. Почему 010, а не 001? Потому что маска "не убивает" разряды, она просто маскирует. Если этот момент вам неясен, тогда взгляните сюда:
111 & 010 = 010
1 & 0 = 0
1 & 1 = 1
1 & 0 = 0
Разряды не пропали.

Но вспомним: 010 у нас лежит в константе b2, а 001 в константе b1. В итоге, достаточно проверить (number & b1) > 0 чтобы понять, горит ли первая лампочка, (number & b2) > 0 чтобы понять, горит ли вторая. Заметьте, используя константы совсем нету необходимости помнить что какое число означает и делать какие-то сложные операции.
К слову, такой механизм реализован в Array.sort.

Теперь практическое применение сдвигов: предположим, у вас есть какой нибудь цвет, например 0x45FF15 и вам нужно узнать каждую его составляющую - красный, зеленый и синий. Зная битовые операции, нет ничего проще!

Начнем с синего. Синий цвет - это последние две цифры, нужно замаскировать остальные и оставить просто их. Да-да, замаскировать - значит наложить маску, осталось понять какую. А очень простую - 0x0000FF. Число 0x45FF15 - это 3 байта: третий байт 0x45, второй 0xFF, первый байт 0x15. 0x - это префикс, означающий что дальше пойдёт число в шестнадцатеричном исчислении.
Значит, нам нужно сделать маску, чтобы второй и третий байты были нулями, а всё в первом байте было единицами. Это позволит нам "убить" второй и третий байты, а первый байт мы оставим в первозданном виде. Значит, второй и третий байт должны быть по 0x00, а третий байт должен быть заполнен полностью единицами, то есть нести число 255 или 0xFF - это десятичная и шестнадцатеричная запись одного и того же числа, о чем рассказывалось ранее. Отсюда и получаем: 0x0000FF.
(0x45FF15 & 0x0000FF) = 0x000015
Нули справа незначимы - поэтому результат и есть 0x15 - то что нам нужно!

Теперь нужно взять второй байт - зеленый. Мыслим логически: сперва нужно спрятать все байты кроме второго. Аналогично

(0x45FF15 & 0x00FF00) = 0x00FF00

Хм, получилось, но не совсем... Вот бы сдвинуть FF вправо. Слово сдвинуть не о чем не напоминает? Именно, о сдвигах. Но на сколько сдвинуть? Сдвигаем мы на столько, чтобы правый байт ушел в небытие. А в байте 8 битов. Значит, нужно сдвинуть на 8!
0x00FF00 >> 8 = 0x0000FF = 0xFF
Получили заветное число. Как получить красный? "Наверное, нужно наложить маску на красный, а потом сдвинуть!" - скажете вы. Но всё ещё проще: правые байты уйдут вправо в небытие, оставив только третий байт, а слева вдвинуться нули - поэтому достаточно просто сдвинуть это дело на 16, т.е. на 2 байта:
(0x45FF15 >> 16) = 0x000045 = 0x45

В конце хочу сказать, что флеш предоставляет отличный метод у всех числовых типов: toString, который имеет аргумент radix. Он позволяет выводить число в любой системе исчисления. Например, чтобы увидеть результат (16 << 3) в двоичной системе достаточно ввести

Код AS3:
trace((16).toString(2), "<<", 3, (16 << 3).toString(2));
А чтобы увидеть число 255 в шестандцатеричной:
Код AS3:
trace((255).toString(16));
(Скобки написаны ради того, чтобы компилятор воспринимал точку как оператор, а не как разделитель между дробной и целой частью).

Следует заметить, что в статье рассмотрены не все бинарные операторы.
Если тема вам интересна - предлагаю продолжить самообучение, например, отсюда.

Таким образом биты - это совсем не страшно, а вполне хороший инструмент для работы. Но и как любой инструмент его нужно применять там, где нужно. Например, пример с 8 флагами очень хорош для передачи по интернет-соединению, такому как сокет - вы будете экономить трафик сервера и пользователя, но не нужно ради какого-нибудь класса всего с 2 флагами вводить подобный трюк. Трюков с битами достаточно много - например ранее я рассказывал об умножении и делении на 2 путём сдвига, битовыми операциями можно делить с остатком и ещё много чего. Просто ищите, экспериментируйте и делитесь своим опытом с коллегами.
Всего комментариев 72

Комментарии

Старый 30.08.2010 15:22 Волгоградец вне форума
Волгоградец
 
Аватар для Волгоградец
Молодец, хорошая статья, и полезная. Жду не дождусь когда про байткод начнешь писать .
Старый 30.08.2010 16:16 AS3Coder вне форума
AS3Coder
 
Аватар для AS3Coder
Еще советую посмотреть книгу "What can you do with bytes?" от Thibault Imbert. Книга написана на простом английском.
Старый 30.08.2010 16:46 BlooDHounD вне форума
BlooDHounD
 
Аватар для BlooDHounD
это не логические операторы а бинарные. логические это && и ||
и почему так выборочно выбраны операторы? где ~, где ^, где >>> ?
Старый 30.08.2010 17:34 i.o. вне форума
i.o.
 
Аватар для i.o.
Тигер, с вычленением каналов цвета не совсем правильно поступаешь, а именно с красным.
Ты просто сдвигаешь на 16 бит вправо число и получаешь "красный". Все хорошо, пока слева от канала красного стоят нули. Если там будет что-то другое, то сам понимашь, охват "красного" слегка расширится
Вообще принято извлекать и объединять каналы цвета так:
Код:
A = colorARGB >> 24 & 0xFF,
R = colorARGB >> 16 & 0xFF,
G = colorARGB >> 8 & 0xFF,
B = colorARGB & 0xFF;

colorARGB = A << 24 | R << 16 | G << 8 | B;
Обновил(-а) i.o. 30.08.2010 в 19:41
Старый 30.08.2010 18:04 switcher! вне форума
switcher!
Цитата:
и почему так выборочно выбраны операторы?
По остальным, если интересно, суть можно и в хелпе посмотреть. База-то дана.

Однако, если с положительными числами все просто, то с отрицательными есть некоторые нюансы, которые хотелось бы прояснить.
Когда-то я копался в битовых операциях и все было ясно и понятно. А потом прочитал в хелпе, что "-1" в двоичном виде выглядит как "11111111111111111111111111111111 (32 единицы)". Аналогично и другие числа. И вот тут я впал в ступор. Откуда виртуальная машина знает, что "11111111111111111111111111111111" - это "-1" в двоином виде, а не скажем uint.MAX_VALUE ?
Сперва проверяется uint/int ? Не вопрос... Откуда машина знает, что это, скажем, не есть отрицательное "15", представление которого в одном байте "00001111" ?
Локика такая (судя по хелпу):
*) "двоичное представление" - "десятичное представление"
1) "11111111111111111111111111111111" - "-1"
2) "11111111111111111111111111111000" - "-8"
3) ????? - "-15"

Логично было бы увидеть так:
*) "двоичное представление" - "десятичное представление"
1) "10000000000000000000000000000001" - "-1"
2) "10000000000000000000000000001000" - "-8"
3) "10000000000000000000000000001111" - "-15"
где крайний левый разряд отвечает за знак. Но имеем то, что имеем. Просьба знающим людям разъяснить.

toAS3Coder:
==================
"Enter the password: ...
Книга написана на простом английском.
Checking... Access Granted!"
==================
забираю, спасибо
Обновил(-а) switcher! 30.08.2010 в 18:07
Старый 30.08.2010 18:17 BlooDHounD вне форума
BlooDHounD
 
Аватар для BlooDHounD
@i.o.
если 32 бита сдвинуть на 24 вправо, то останется 8. поэтому если заменить >> на >>>, то можно обойтись одним оператором.
@switcher!
целые числа занимают в памяти 4 байта. если выделять специальный байт под знак, то появляются проблемы с изменением размерности, и с хранением в бинарном виде. поэтому считает, что ты сам должен знать знак при чтении целых чисел. в данном это случаи это информация хранится в типе (u)int.
Старый 30.08.2010 18:38 switcher! вне форума
switcher!
Цитата:
что ты сам должен знать знак при чтении целых чисел. в данном это случаи это информация хранится в типе (u)int
Я мог бы понять, если бы это означало следующее:
"Есть объект класса int. Дыбы сэкономить место и не заводить 4 байта под -15, машина заведет на объект один байт на 15 ("1111"), а другой (байт?) на знак"
Но, видимо, я не улавливаю момент:
Цитата:
то появляются проблемы с изменением размерности
И с учетом сказанного ранее, есть вопрос:
Цитата:
если выделять специальный байт под знак
так мы же его (байт) не выделяем. Знак обозначается в одном разряде, т.е. 1 бит, и если мне не изменяет память - этот разряд крайний левый. Таким образом в 32-х разрядах мы можем разместить либо от 0-ля до uint.MAX_VALUE, либо от int.MIN_VALUE до int.MAX_VALUE (поскольку один разряд "съедается" под знак")
Старый 30.08.2010 18:55 Psycho Tiger вне форума
Psycho Tiger
 
Аватар для Psycho Tiger
2Blood: тьфу, бинарные. Спасибо за поправку, чуть позже поправлю. Да, switcher прав по поводу "базы" - мне кажется эти три оператора главные. Я постарался дать "понимание" битов и какая в них есть польза, остальное я предлагаю дать читателю. Я считаю, что гораздо больше пользы человек получит, если нужную информацию изучит сам, проделав свои тесты. В случае если я разжевывать очень много - статья будет уже сложной, чтобы её осилить и у человека не будет просторов для размышлений - он попросту не будет пытаться найти ещё полезностей от бинарных операций. Я рассмотрел основную - извлечения части числа на примере флагов и цвета. Дальше читатель должен идти сам.

2i.o, ну я рассматривал пример RGB, а не ARGB, причем конкретный. Я ведь не писал что цвет вычисляется именно так.

2switcher! Ага, статья про uint`ы. Ещё есть дробные числа, у них своё представление. Замечания понял, допишу что на примере uint`ов.

Ещё проверю статью на ряд неточностей. Например, я писал что при сдвиге влево байт выделяется, когда на самом деле он выделен и там просто нули. Я не писал про переполнение (я про carry flag). Спасибо за комментарии.

2Волгоградец: максимум что я могу сейчас уверенно написать - это как взять header у флешки (фреймрейт, размер, "вес", количество кадров в руте...), с остальным пока все ещё разбираюсь. Я не знаю только, стоит ли написать как сделать вот такой вот "читатель" с флешки, не рассказав вообще о структуре байткода? Как считаешь?


P.S. Блуд, с каждым твоим сообщением я проникаюсь к тебе всё большим уважением. Поделись секретом (можно на ты?), ты изучал это на собственных тестах или есть какие-то источники, где про это рассказано?
Старый 30.08.2010 19:15 BlooDHounD вне форума
BlooDHounD
 
Аватар для BlooDHounD
@Psycho Tiger
эээ я в школе информатику на отлично сдал. поэтому не очень понимаю сути вопроса о источниках. лично мне это в 8м классе всё рассказали.

@switcher!
представьте в бинарном виде запись 2х чисел по 4 байта каждое. по сути мы можем подумать и захотеть сделать из них 8 по 1 байту. так вот в вашем случаи из ниоткуда возьмётся непонятный байт с непонятным битом. а в случаи с 2мя числами, байтов будет 2. и записывали 8 байт, а получили 10. и вообще, процессор не работает со знаками, он работает, как было сказано выше, с битами. знак это человеческая приблуда. к тому же само число по сути знака не имеет. знак имеет значение только при арифметических операциях, и при выводе на экран.

обычно при операции с битами знак становится не важен. то есть, если вы начали оперировать битами, то нафига вам знак? вам нужны всякие маски и значения в битах. а исходное число может быть хоть положительным, хоть отрицательным. на результат это не влияет.
Старый 30.08.2010 19:34 incvizitor вне форума
incvizitor
 
Аватар для incvizitor
BlooDHounD, мы вот когда в школе ассемблер учили, просто создавали указатели на данные, но как бы мы сами знали что и где храниться, поэтому просто присваивали те или иные значения указателям. А вот как компилятор определяет что за тип данных перед ним? Oткуда ему читать информацию о представлении числа, из типа int или uint? Или в указателе есть нейкое обозначение типа данных на который мы ссылаемся? (тут я говорю не только об AS3, а в общем).

Извините, если вопрос не ясно истолкован.
Старый 30.08.2010 19:41 BlooDHounD вне форума
BlooDHounD
 
Аватар для BlooDHounD
чего в var напишите так он и распознает.
Старый 30.08.2010 19:51 incvizitor вне форума
incvizitor
 
Аватар для incvizitor
Это я понимаю

Но вот я написал ему в var тип, что он с ними делает? Где он сохраняет тип? Я это к тому что если у нас например есть переменная uint, то где то же при компиляции сохраняються еще и данные что она именно uint и так её и надо предствалять?
Старый 30.08.2010 20:25 Psycho Tiger вне форума
Psycho Tiger
 
Аватар для Psycho Tiger
@BlooD: я не о сдвигах, и даже не конкретно об этой теме, а вообще. Ну, даже на текущем примере - откуда ты узнал, что флеш берёт информацию о числе из типа?
Сам догадался из тестов и изучения нужной тебе темы или есть какие-то супер-секретные статьи, к которым допускаются только избранные?

incvizitor, тут уже я рискну ответить. В байткоде:
Код:
 // var a:int=10;
pushbyte 10
convert_i 
setlocal1         /* a */
  //     var b:uint = 10;
pushbyte 10
convert_u 
setlocal2
Сохраняет, значит.
Обновил(-а) Psycho Tiger 30.08.2010 в 20:30
Старый 30.08.2010 20:34 incvizitor вне форума
incvizitor
 
Аватар для incvizitor
Psycho Tiger, дело в том что байткод - не самый нижний уровень, есть еще и машинные инструкции. То что сохраняет в баткоде != то что сохраняет на уровне ассемблера.

С первого дня как я открыл книгу по С++, я свято верил что тип int занимает 4 байта. То что он где то сохраняет - явно. Вопрос только в том, сохраняет он это из сегмента данных, или в сегменте кода создаёться нейкая таблица, или еще как ни будь?
Старый 30.08.2010 20:39 Psycho Tiger вне форума
Psycho Tiger
 
Аватар для Psycho Tiger
AS3Coder, спасибо за ссылку, но это убило)
Цитата:
• 1 kilo-byte (kb) = 10³ bytes (1 000 bytes) ;
• 1 mega-byte (mb) = 106 bytes = 1 000 kb (1 000 000 bytes).
Старый 30.08.2010 20:51 Psycho Tiger вне форума
Psycho Tiger
 
Аватар для Psycho Tiger
Кстати Блуд, можешь объяснить что ты имел ввиду под
Цитата:
если 32 бита сдвинуть на 24 вправо, то останется 8. поэтому если заменить >> на >>>, то можно обойтись одним оператором.
речь ведь шла о ARGB, а там отрицательных чисел быть не может. Поэтому >> или >>> нет разницы ведь? Или есть?
Старый 30.08.2010 21:01 BlooDHounD вне форума
BlooDHounD
 
Аватар для BlooDHounD
Psycho Tiger, ну откуда я могу знать такие вещи? я без понятия откуда он её берёт. я не смотрел эту часть устройства avm. я знаю лишь 4 байта - это 32 бита. а не 31.

и это ... видимо тему сдвигов ты не просёк до конца. попробуй сдвинуть белый на 24 обоими способами и поймёшь.
Старый 30.08.2010 21:54 Psycho Tiger вне форума
Psycho Tiger
 
Аватар для Psycho Tiger
Да, уже вижу и уже нашел информацию о том, откуда это.

И да, извини за то что так докапываюсь по поводу устройства этих вещей. Я вижу что ты пишешь и как ты пишешь, и ты у меня ассоциируешься если не с лучшим, то с одним из лучших флешеров и видимо детский максимализм шепчет, что ты наверняка знаешь всё-всё-всё. Это без лести, правда.) Ещё раз извини.
Старый 30.08.2010 22:27 dimarik вне форума
dimarik
 
Аватар для dimarik
Очень интересная статья.
Интересно, решен ли вопрос о переносе влево через флаг C?
Старый 30.08.2010 22:42 Psycho Tiger вне форума
Psycho Tiger
 
Аватар для Psycho Tiger
dimarik, нет, вопрос не решен. Я постарался дать понятие, что биты - это просто и никакой магии в этом нет. Если человеку будет интересна эта тема - он её сам проработает и сделает свои выводы, пользы от этого больше.

Если ты имеешь ввиду мой вопрос, который ты мне задал ещё давно - то нет, не решен. Я так и не смог найти этому делу практическое применение. Буду очень рад если поделишься мыслью, как это можно применить.

Вопрос к BlooD`у и всем остальным, кто просёк фишку с >> при работе с 32-битными объектами:
Цитата:
>> (Bitwise right shift) : Converts expression and shiftCount to 32-bit integers, and shifts all the bits in
expression to the right by the number of places specified by the integer that results from the conversion
of shiftCount.
"Артефакты" вылазят потому что не хватает "места" для операций, вследствии чего наиболее значащий бит интерпретируется как знак?
Старый 30.08.2010 23:21 switcher! вне форума
switcher!
Цитата:
представьте в бинарном виде запись 2х чисел по 4 байта каждое. по сути мы можем подумать и захотеть сделать из них 8 по 1 байту.
А как это планируется сделать? Интересует сам принцип.
Например, из числа 0xAACC2233, записанного 4-мя байтами => получить 0xAA, 0xCC, 0x22, 0x33 каждый в своем байте?

Цитата:
обычно при операции с битами знак становится не важен. то есть, если вы начали оперировать битами, то нафига вам знак?
То есть как это не важно, как зачем ? В выражении:
Код AS3:
(num & 200)
мы получим совершенно разные результаты для положительного и отрицательного num, хоть и равного по модулю.
Старый 30.08.2010 23:39 dimarik вне форума
dimarik
 
Аватар для dimarik
Знак - это один старший бит. Только контекст типа определяет то, как этим знаком воспользоваться - считать его как sign или присудить к разрядности.
Старый 30.08.2010 23:58 switcher! вне форума
switcher!
я в курсе, спасибо. Мы немного о другом говорим -)
Старый 31.08.2010 00:00 dimarik вне форума
dimarik
 
Аватар для dimarik
Я рад, что мы говорим об одном и том же.

Цитата:
обычно при операции с битами знак становится не важен.
то есть, если вы начали оперировать битами, то нафига вам знак?
Имеются ввиду именно операции с битами. Знаки тут не играют роли - на этой стадии их просто нет. А контексты появляются позже - на стадии "узнавания" числа.
Обновил(-а) dimarik 31.08.2010 в 00:18
Старый 31.08.2010 00:08 dimarik вне форума
dimarik
 
Аватар для dimarik
Цитата:
Я так и не смог найти этому делу практическое применение.
Флаг переноса и операции с ним позволяют "конструировать" число.
Старый 31.08.2010 00:21 switcher! вне форума
switcher!
Цитата:
Я рад, что мы говорим об одном и том же.
безусловно, мы все тут говорим о flash, о программировании, etc...

Но мы с BlooDHounD - конкретно о типе, который может принимать отрицательные значения и умещается в 32 разряда для представления числа, т.е. о int (Integer).
Соответственно, речь о том, что крайние левый разряд может быть использован под что-то иное нежели sign - не идет. -)
Старый 31.08.2010 00:32 dimarik вне форума
dimarik
 
Аватар для dimarik
а если uint? тоже вроде 32 и там речи про знак нет.
Имеются ввиду именно операции с битами. Я дополнил предыдущий комментарий.
Старый 31.08.2010 00:55 Psycho Tiger вне форума
Psycho Tiger
 
Аватар для Psycho Tiger
dimarik, вроде бы я тебе про это говорил, но ты сказал что я не о том. Повторюсь: CF на флеше нужен при сдвиге числа влево, чтобы знать было ли переполнение, т.е. реальный ли результат у нас лежит в после сдвига.
Реализовывал я бы как то так:
Код AS3:
public function carryFlag(value:uint, shift:uint):Boolean{
return Boolean(value >> (32 - shift));
}
Я опять не о том?
Насчет 32 не уверен, голова плохо варит. Опять в 3 ночи сижу за компом.)
Старый 31.08.2010 00:57 switcher! вне форума
switcher!
Тигр, а что понимается под "Артефактом"? Вылезшие за границы разряды ?
Обновил(-а) switcher! 31.08.2010 в 01:10
Старый 31.08.2010 03:00 BlooDHounD вне форума
BlooDHounD
 
Аватар для BlooDHounD
switcher! модуль числа тут вообще не причём.
в Вашем примере результат будет одинаков независимо от того имеет ли num тип int или uint. Вы кажется не понимаете смысла всего этого барахла.
Старый 31.08.2010 09:08 Psycho Tiger вне форума
Psycho Tiger
 
Аватар для Psycho Tiger
switcher!, ну в принципе да. Отрицательное число, например при сдвиге на 24 бита >>, когда последние два разряда положительные. Я не понимаю, откуда оно берётся если смотреть с точки зрения битов. Если при << даётся 4 байта и при сдвиге левая единичка может рассматриваться как минус, то с >> мне совсем не понятно, откуда там минус.
Старый 31.08.2010 09:54 i.o. вне форума
i.o.
 
Аватар для i.o.
Тигер, все очень просто.
>> вставляет нолики, если крайний левый регист - ноль. Или же вставляет единички, если крайний левый регист - единичка. Сделано это для того, чтобы можно было корректно оперировать и с отрицательными числами.
А для того, чтобы всегда вставлять нули слева при сдвиге есть оператор >>>.
Вот поэтому при извлечении альфы с помощью >> у тебя получатся правильные результаты только если AA <= 0x7F. Все, что выше - посчитается как отрицательное число, и слева вставятся единички вместо нулей.
Старый 31.08.2010 09:57 Psycho Tiger вне форума
Psycho Tiger
 
Аватар для Psycho Tiger
Ага, т.е. смотри как получается:
Есть uint, но он настолько большой, что у него крайний левый бит единица.
Знаковый >> распознает его как знак и вставляет нули за ним, отсюда и минус.
И правда, всё проще чем я думал. Спасибо большое. )
Старый 31.08.2010 10:32 i.o. вне форума
i.o.
 
Аватар для i.o.
Не совсем. >> только смотрит крайний левый бит 0 или 1 и вставляет 0 или 1 соответственно.
>> вообще не в курсе, что есть какие то там знаки.
Знаками занимается int и для него (это ты и так наверняка знаешь, просто еще раз объясню) все что <= 0x7FFFFFFF (+2147483647 для int) является положительным, а все что >= 0x80000000 (-2147483648 для int) - отрицательным.
Это, кстати, как раз отвечает на вопрос switcher!.
Вот тем и удобно. Гипотетически представь, что мы оперируем даже не с int32, а с int5. И решили мы разделить его так:
положительные от 00000(+0) до 01111(+15). Общепринято в AS3 также.
отрицательные от 10000(-0) до 11111(-15). Общепринято в AS3: 10000(-16) до 11111(-1).
А теперь нам нужно скажем из 00001 вычесть 00010 (т.е 1 - 2 = -1)
В результате вычитания мы получим 11111. Таким образом при переводе в наш int5 мы получим -15 0_o. А при переводе в общепринятый int5 -1.
Т.е с нашим int5 нам понадобятся еще дополнительные усилия, чтобы понять к чему этот результат относить, а потом, если мы определили, что это отрицательный, то еще и преобразовывать к соответствующему виду, т.е 11111 превращать в 10001.
Обновил(-а) i.o. 31.08.2010 в 12:45
Старый 31.08.2010 10:36 Psycho Tiger вне форума
Psycho Tiger
 
Аватар для Psycho Tiger
Да, я примерно это и сказал, только плохо мысль выразил. Ещё раз спасибо)
Старый 31.08.2010 12:11 switcher! вне форума
switcher!
Люди... о чем вы?
В as3 представление отрицательного числа в битах (Integer) происходит посредством дополнительного кода. Люди, знающие и понимающие, не могли не заметить, что упор в своих рассуждениях я делал на прямой код, хотя изначально шел в своих рассуждениях по неверной дорожке.
Это я и хотел услышать с самого начала, но на тот момент не владел понятиями.
КАК к этому относится разбиение 4-х байт на байты? При любом из способов представления числа знаковый бит все тот же - крайний левый. И хотите вы того или нет, при любом отрицательном числе с ним придется считаться.
КАК к этому относится однородность представления положительных чисел в uint и int, когда я изначально спрашивал про отрицательные числа?

Цитата:
положительные от 0000(+0) до 01111(+15). Общепринято также.
отрицательные от 1000(-0) до 11111(-15). Общепринято: 1000(-16) до 11111(-1).
В as3, как я уже сказал, числа представлены в дополнительном коде. Вы говорите о прямом коде. И при этом совершенно не замечаете, что int.MAX_VALUE и int.MIN_VALUE по модулю разнятся на единицу, что при прямом коде невозможно.
Соответственно, нет отрицательного нуля и число «-15» (если сузить до 5-ти бит) представлено как 10001.

Я не придираюсь и никого не ругаю. Я говорю то, что вижу. Возможно резкость моя не оправдана - прошу простить. Но иного мнения у меня пока нет.
Старый 31.08.2010 12:30 i.o. вне форума
i.o.
 
Аватар для i.o.
"Общепринято" - имелось ввиду "принято в AS3", т.е дополнительный код.
Цитата:
Вы говорите о прямом коде. И при этом совершенно не замечаете, что int.MAX_VALUE и int.MIN_VALUE по модулю разнятся на единицу, что при прямом коде невозможно.
Ну вы же сами сказали, что int в AS3 в доп. коде, и при этом удивляетесь, что
Цитата:
int.MAX_VALUE и int.MIN_VALUE по модулю разнятся на единицу
Вот при прямом такое как раз невозможно.

Цитата:
Соответственно, нет отрицательного нуля и число «-15» (если сузить до 5-ти бит) представлено как 10001.
Даже в статье Дополнительный_код в первой же таблице идет речь об отрицательном нуле при прямом коде.
Цитата:
число «-15» (если сузить до 5-ти бит) представлено как 10001
Да, опечатался, извиняюсь
Обновил(-а) i.o. 31.08.2010 в 12:39
Старый 31.08.2010 12:41 switcher! вне форума
switcher!
Цитата:
"Общепринято" - имелось ввиду "принято в AS3", т.е дополнительный код.
оке, понял.

Цитата:
и при этом удивляетесь
где вы в констатации факта увидели удивление?

Цитата:
switcher!
при прямом коде невозможно.

i.o.
при прямом такое как раз невозможно
чувствуете разницу? Я - нет.

Цитата:
в первой же таблице идет речь об отрицательном нуле при прямом коде.
оу, речь не о прямом коде. Забудьте про него. Его в as3 судя по всему нет вообще.
Обновил(-а) switcher! 31.08.2010 в 12:43
Старый 31.08.2010 12:55 i.o. вне форума
i.o.
 
Аватар для i.o.
Цитата:
Цитата:
Цитата:
положительные от 00000(+0) до 01111(+15). Общепринято также.
отрицательные от 10000(-0) до 11111(-15). Общепринято: 10000(-16) до 11111(-1).
В as3, как я уже сказал, числа представлены в дополнительном коде. Вы говорите о прямом коде. И при этом совершенно не замечаете, что int.MAX_VALUE и int.MIN_VALUE по модулю разнятся на единицу, что при прямом коде невозможно.
Я вот что-то непойму. Где вы меня цитируете, так вот там вначале речь про прямой код идет, а потом, после точки, где "общепринято", про дополнительный.
После этого говорите:
Цитата:
И при этом совершенно не замечаете, что int.MAX_VALUE и int.MIN_VALUE по модулю разнятся на единицу, что при прямом коде невозможно
Не совсем понял к чему это и как int.MAX_VALUE и int.MIN_VALUE относятся к моему рассмотрению примера с int5 (Тем более вы сами сказали, что int представлен в дополнительном коде, а на примере я рассматриваю прямой). Но вот в этом примере ясно видно, что при прямом коде разницы в единицу нет:
Цитата:
положительные от 00000(+0) до 01111(+15)
отрицательные от 10000(-0) до 11111(-15)
|+15| - |-15| = 0
Цитата:
И при этом совершенно не замечаете
Где я такое не заметил??
Обновил(-а) i.o. 31.08.2010 в 13:00
Старый 31.08.2010 13:15 switcher! вне форума
switcher!
Цитата:
Я вот что-то непойму
я уже написал, что не понял, что вы сперва описали прямой код, а затем дали представление в AS3 в дополнительном через "общепринято".

Код AS3:
при прямом коде разницы в единицу нет
я где-то сказал об обратном?

Что касается участия прямого кода в AS3, то меня терзали смутные сомнения. Проверил справку по программированию от Adobe и, действительно:
"тип данных Number, с помощью которого можно обрабатывать значения в промежутке между положительным и отрицательным значением 9007199254740992 (53-разрядные целые значения)"
похоже на прямой код. Но надо еще проверить битовыми операциями.
Старый 31.08.2010 13:19 i.o. вне форума
i.o.
 
Аватар для i.o.
Насколько помню, так Number всегда был double (число двойной точности, мантисса 52 бита).
Старый 31.08.2010 13:31 switcher! вне форума
switcher!
если для вас "double (число двойной точности, мантисса 52 бита)" автоматически означает, что числи записывается посредством прямого кода - это круто.

Для меня же как человека совсем недавно узнавшего, что существует отличный от прямого кода способ представления чисел в двоичном виде - это весьма не очевидно.
Старый 31.08.2010 13:37 i.o. вне форума
i.o.
 
Аватар для i.o.
Цитата:
Прямой код — способ представления двоичных чисел с фиксированной запятой в компьютерной арифметике
Число двойной точности - число с плавающей запятой.
Старый 03.09.2010 22:32 dimarik вне форума
dimarik
 
Аватар для dimarik
Резюме. Операций с битами в AS нет. Только эрзац.
Старый 03.09.2010 23:13 Psycho Tiger вне форума
Psycho Tiger
 
Аватар для Psycho Tiger
dimarik, это ирония или ты серьезно? На мой взгляд штатных |, ~, &, <<, <<< вполне хватает.
Объясни мне как нибудь в аську о реальной пользе CF в высокоуровневых языках. Я этим уже всех знакомых программистов достал, никто не знает =)
Старый 04.09.2010 00:51 BlooDHounD вне форума
BlooDHounD
 
Аватар для BlooDHounD
<<< - что за звеР такой?
Старый 04.09.2010 01:18 dimarik вне форума
dimarik
 
Аватар для dimarik
Здесь описаны сдвиги.

Есть последовательность битов, например, в формате SWF файла. Именно битов! Так задан RECT, MATRIX и некоторые другие теги. Эта последовательность имеет переменную длину. Чтобы работать с этими числами необходимо сделать преобразование. Очень удобно работать именно с битами через непосредственно сдвиги в другое хранилище (переменную). Такого инструмента AS не предоставляет. Т.е. нет у нас
Код AS3:
foo = 0000 0100;
bar = 0000 0001; RR(foo, bar, 2);
trace(foo, bar) // 0100 0001b, 0000 0000b
при котором в foo попадает два бита сдвинутых вправо из bar. На размерность не обращайте внимания.

Низкоуровневые команды процессора позволяют в операциях сдвига через CF как левый так и правый сдвиг. Здесь CF выполняет не совсем свою "обязанность". Вот команды вращения регистров Z80.



Где t - название регистра. Для нас равносильно названию переменной (типа int, uint)
Обновил(-а) dimarik 04.09.2010 в 01:23
Старый 04.09.2010 01:24 Котяра вне форума
Котяра
 
Аватар для Котяра
Причём здесь высокоуровневые языки?
Код AS3:
    .model tiny
    .code
    .startup
    mov dx, offset Hello
    mov ah, 9
    int 21h
    .exit
    Hello db 'Hello world!$'
    end
Оно тебе надо?
или всё таки
Код AS3:
trace("Hello world!")
Старый 04.09.2010 01:27 Котяра вне форума
Котяра
 
Аватар для Котяра
Цитаты из вики, но в своё время кодил на масме очень плотно (сейчас аж жуть берёт, как вспомню)
нафик-нафик..
Старый 04.09.2010 01:42 dimarik вне форума
dimarik
 
Аватар для dimarik
А мне нравилось. Я battle city пытался портировать на zx-spectrum когда учился в институте. Кодил в Zeus. Это такое IDE, как сказали бы сейчас )
Аха. Я такой старый. В мои времена был Поиск, БК, ДВК, Вектор-06ц, Корвет, Орион и MSX-2 (до сих пор имею на ноуте эмулятор этого шедевра).
Обновил(-а) dimarik 04.09.2010 в 01:47
 

 


Часовой пояс GMT +4, время: 20:09.


Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2019, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.