Этот баннер — требование Роскомнадзора для исполнения 152 ФЗ.
«На сайте осуществляется обработка файлов cookie, необходимых для работы сайта, а также для анализа использования сайта и улучшения предоставляемых сервисов с использованием метрической программы Яндекс.Метрика. Продолжая использовать сайт, вы даёте согласие с использованием данных технологий».
Политика конфиденциальности
|
|
|
Битовые сдвиги.
|
|||
|---|---|---|---|
|
#18+
Здравствуйте. 1. Я разбирал функцию возвращающую количество единиц в двоичном представлении целого числа int: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. Эта функция работает, и я понимаю каждую строчку в этом коде, но мне непонятно почему она работает ? То есть я не понимаю почему такой алгоритм ? Например, в функции возвращающей третий угол треугольника в евклидовой геометрии float angle(float an1,float an2) {return 180-an1-an2;} я понимаю всё, и код, и откуда цифра 180, а в функции count я понимаю код, но не понимаю почему. Объясните пожалуйста. 2. Прокомментируйте пожалуйста следующее предложение, оно взято по следующей ссылке http://msdn.microsoft.com/ru-ru/library/vstudio/8xftzc7e(v=vs.100).aspx " Чтобы при каждом сдвиге оставался хотя бы один исходный бит, операторы сдвига используют следующую формулу для вычисления фактической величины сдвига: маска выражения expression2 (использующая побитовый оператор И) с числом, на единицу меньшим, чем количество битов в выражении expression1. " Спасибо ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 23.01.2014, 09:05 |
|
||
|
Битовые сдвиги.
|
|||
|---|---|---|---|
|
#18+
Тема видимо названа некорректно, к сожалению не знаю как изменить название. Первоначально меня интересовал второй вопрос больше, потому назвал тему исходя из содержания второго вопроса ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 23.01.2014, 09:07 |
|
||
|
Битовые сдвиги.
|
|||
|---|---|---|---|
|
#18+
a&=(a-1); сбрасывает в ноль младший двоичный разряд равный 1. Выводи двоичное значение "а" при каждой итерации цикла. Увидишь как меняется, поймешь. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 23.01.2014, 09:50 |
|
||
|
Битовые сдвиги.
|
|||
|---|---|---|---|
|
#18+
Dima T, спасибо за ответ. Я понимаю каждую строчку этого кода, и понимаю как что меняется. Без вывода на экран, и без рисования на листке. Мне непонятно доказательство данного алгоритма, скажем так обоснование данного метода, если говорить математическим языком "сбрасывает в ноль младший двоичный разряд равный 1. " почему он сбрасывается ? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 23.01.2014, 09:54 |
|
||
|
Битовые сдвиги.
|
|||
|---|---|---|---|
|
#18+
SashaMercury"сбрасывает в ноль младший двоичный разряд равный 1. " почему он сбрасывается ? -1 приводит к инвертированию всех разрядов начиная с младшего до первого равного 1 (включительно), а 1&0 = 0&1 = 0 Например a=20 или 10100 в двоичном виде (а-1) = 19 = 10011 дальше побитовое И: 10100 & 10011 = 10000 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 23.01.2014, 10:00 |
|
||
|
Битовые сдвиги.
|
|||
|---|---|---|---|
|
#18+
Dima T, "-1 приводит к инвертированию всех разрядов начиная с младшего до первого равного 1 (включительно)", почему такое происходит ? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 23.01.2014, 10:14 |
|
||
|
Битовые сдвиги.
|
|||
|---|---|---|---|
|
#18+
Или по другому: вспомни школьное правило вычитания столбиком. Возьми ручку, бумагу и проделай тоже самое только в двоичном виде (X-1). Пока в текущем разряде ноль из следующего старшего разряда будет заниматься единица до тех пор пока в старшем разряде не окажется единицы, эта единица станет нулем и на более старшие разряды никак не повлияет. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 23.01.2014, 10:16 |
|
||
|
Битовые сдвиги.
|
|||
|---|---|---|---|
|
#18+
Понял ))) Минус один, значит число на 1 бит меньше, при вычитании видимо эта инверсия до первой единицы включительно и происходит ) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 23.01.2014, 10:19 |
|
||
|
Битовые сдвиги.
|
|||
|---|---|---|---|
|
#18+
"Или по другому: вспомни школьное правило вычитания столбиком. Возьми ручку, бумагу и проделай тоже самое только в двоичном виде (X-1). Пока в текущем разряде ноль из следующего старшего разряда будет заниматься единица до тех пор пока в старшем разряде не окажется единицы, эта единица станет нулем и на более старшие разряды никак не повлияет. " Дада, спасибо ))Я предыдущий комментарий написал когда ещё не видел, всё логично !) Спасибо, Dima T, первую часть вопроса я определённо понял! Так приятно теперь понимать почему это работает так ! ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 23.01.2014, 10:22 |
|
||
|
Битовые сдвиги.
|
|||
|---|---|---|---|
|
#18+
SashaMercuryПонял ))) Минус один, значит число на 1 бит меньше, при вычитании видимо эта инверсия до первой единицы включительно и происходит ) Минус один, значит на один меньше ))) Двоичная арифметика ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 23.01.2014, 10:26 |
|
||
|
Битовые сдвиги.
|
|||
|---|---|---|---|
|
#18+
я имел ввиду что минус один значит f e: 00010100 вычесть 00000001 , под 00000001 я имел ввиду один бит, обозвал неправильно. Я понял ! 00010100 - 00000001 00010011 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 23.01.2014, 10:35 |
|
||
|
Битовые сдвиги.
|
|||
|---|---|---|---|
|
#18+
SashaMercury2. Прокомментируйте пожалуйста следующее предложение, оно взято по следующей ссылке http://msdn.microsoft.com/ru-ru/library/vstudio/8xftzc7e(v=vs.100).aspx " Чтобы при каждом сдвиге оставался хотя бы один исходный бит, операторы сдвига используют следующую формулу для вычисления фактической величины сдвига: маска выражения expression2 (использующая побитовый оператор И) с числом, на единицу меньшим, чем количество битов в выражении expression1. " Это про битовый сдвиг переменной X на N разрядов при N больше или равно чем всего разрядов в X. По идее всегда должно получаться 0. Например размер X 1 байт, т.е. 8 бит, сдвинув на 10 исходное значение уйдет за пределы переменной. ХЗ зачем решили усовершенствовать данную ситуацию, но в данном примере сдвиг будет на 2 разряда 10 & (8-1) или в двоичном виде 1010 & 0111 = 0010. Как предположение: возможно процессор так работает, тупо игнорирует лишнее в N, берет три младших бита из N для сдвига в одном байте. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 23.01.2014, 10:47 |
|
||
|
Битовые сдвиги.
|
|||
|---|---|---|---|
|
#18+
Dima T, спасибо. В целом, я понял что происходит, но не понял почему. Мне кажется что это используется для вычисления чего-либо. То есть исходя из логики, зачем сдвигать на 10 бит, если размер типа данных 8 бит, очевидно что будет 0, вот и придумали сдвиг. Кстати. если 10, то получим 2. А если например 24, то тогда: 00011000 &00000111 00000000 Получили 0 А если 13, предполагаю что получим 5 00001101 &00000111 00000101 Получили 5. То есть фактически происходит операция деление по модулю с размером в битах типа данных. Всё-же очень интересно где это используется, не случайно это так ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 27.01.2014, 02:43 |
|
||
|
Битовые сдвиги.
|
|||
|---|---|---|---|
|
#18+
Dima TХЗ зачем решили усовершенствовать данную ситуацию, но в данном примере сдвиг будет на 2 разряда 10 & (8-1) или в двоичном виде 1010 & 0111 = 0010. Как предположение: возможно процессор так работает, тупо игнорирует лишнее в N, берет три младших бита из N для сдвига в одном байте. Эта самодеятельность полностью соответствует стандарту. С++03 / 5.8 Shift operatorsThe behavior is undefined if the right operand is negative, or greater than or equal to the length in bits of the promoted left operand Т.е. какой результат будет если сдвиг больше битовой ширины типа - неопределено. Это может быть как 0 так и вообще случайное число. Так что, на вот это наложение маски которое делает VS полагаться не стоит, т.к. стандарт не определяет каким должен быть результат в этом случае, и в другом компиляторе может быть по другому. Обратите внимание также на подчеркнутое (promoted). Для операций над короткими типам, меньшими чем int (char, short, bool) проводится расширение разрядности (integral promotion) до размера int. И максимальный размер сдвига, для которого результат гарантирован стандартом, определяется размером int, а не размером конкретного короткого типа. Поэтому, к примеру, 8-битный char можно сдвигать вплоть до 31 (для x86). При этом для сдвига начиная с 8 и до 31 результат будет гарантированно 0, а больший сдвиг - неопределен. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 27.01.2014, 05:10 |
|
||
|
Битовые сдвиги.
|
|||
|---|---|---|---|
|
#18+
SashaMercury... оно взято по следующей ссылке http://msdn.microsoft.com/ru-ru/library/vstudio/8xftzc7e(v=vs.100).aspx Присмотрелся, по ссылке про "Операторы (Visual Studio — JScript)", в Си по другому. Как Анатолий написал. Пример из ссылки на Си Код: plaintext 1. 2. 3. Если посмотреть во что компилируется, то видно что компилятор MSVC все отдает на усмотрение процессора Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. Сам сдвиг выполняется в процессоре в 32-битном регистре eax командой shl. SashaMercuryТо есть исходя из логики, зачем сдвигать на 10 бит, если размер типа данных 8 бит, очевидно что будет 0, вот и придумали сдвиг. Сдвигать 8 бит на 10 незачем, но программы пишут люди и может оказаться что такая ситуация возникнет :) SashaMercuryВсё-же очень интересно где это используется, не случайно это так X << N равносильно X * (2 ^ N) только технически (внутри процессора) гораздо быстрее сдвинуть биты чем умножать и в степень возводить. Используется для работы с битовыми структурами, например у надо в байте хранить два значения A и B, где A старшие 3 бита, B младшие 5. Тогда конечный байт будет С = (A << 5) | B или тоже самое A*2^5 + B и обратное преобразование A = C >> 5 = округлить вниз до целого (C / (2^5)) B = C & 31 = остаток от деления С на 2^5 (31 это 2^5 - 1 или в двоичной 11111) По большому счету все битовые операции нужны для учета специфики работы процессора, он двоичный и работает только с двоичными числами и с битами. Если интересно как выполняется программа процессором - изучай ассемблер. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 27.01.2014, 08:43 |
|
||
|
Битовые сдвиги.
|
|||
|---|---|---|---|
|
#18+
Dima T , "Всё-же очень интересно где это используется, не случайно это так" Этот комментарий был не к смыслу в использование побитовых операций, и сдвигов в частности, это мне понятно. Вопрос был, к той специфической операции в VS, согласно которой при сдвиге на размер больший размеру типа данных, сдвиг происходит на остаток от деления на размер типа данных (накладывается маска на размер сдвига). Но, так как Anatoly Moskovsky указал что в данном случае это только такая работа в VS, и другой компилятор вероятно по другому обработает данную операцию, этот вопрос интересен уже менее. Dima T, Anatoly Moskovsky спасибо C: ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 27.01.2014, 09:18 |
|
||
|
Битовые сдвиги.
|
|||
|---|---|---|---|
|
#18+
"Т.е. какой результат будет если сдвиг больше битовой ширины типа - неопределено. Это может быть как 0 так и вообще случайное число. Так что, на вот это наложение маски которое делает VS полагаться не стоит, т.к. стандарт не определяет каким должен быть результат в этом случае, и в другом компиляторе может быть по другому. Обратите внимание также на подчеркнутое (promoted). Для операций над короткими типам, меньшими чем int (char, short, bool) проводится расширение разрядности (integral promotion) до размера int. И максимальный размер сдвига, для которого результат гарантирован стандартом, определяется размером int, а не размером конкретного короткого типа. Поэтому, к примеру, 8-битный char можно сдвигать вплоть до 31 (для x86). При этом для сдвига начиная с 8 и до 31 результат будет гарантированно 0, а больший сдвиг - неопределен. " Ну очень здоровский комментарий ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 27.01.2014, 09:19 |
|
||
|
Битовые сдвиги.
|
|||
|---|---|---|---|
|
#18+
Anatoly MoskovskyДля операций над короткими типам, меньшими чем int (char, short, bool) проводится расширение разрядности (integral promotion) до размера int. А оно проводится с учётом знаковости или без него? Чисто для информации: в процессоре сдвиги вправо бывают четырёх типов: 1) Арифметический: старший бит расширяется. 2) Циклический: в старший бит заносится значение младшего бита 3) С переносом: в старший бит заносится значение флага переноса 4) "Тупой": в старший бит заносится 0. Posted via ActualForum NNTP Server 1.5 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 27.01.2014, 15:50 |
|
||
|
Битовые сдвиги.
|
|||
|---|---|---|---|
|
#18+
Dimitry SibiryakovА оно проводится с учётом знаковости или без него? Компилятор ставит ассемблерную команду SHL, т.е. "тупой беззнаковый" как я понимаю. Вот откуда ноги растут Intel Architecture Software Developer’s Manual стр. 15 (или 3-624)SAL/SAR/ SHL /SHR—Shift (Continued) Intel Architecture Compatibility The 8086 does not mask the shift count. However, all other Intel Architecture processors (starting with the Intel 286 processor) do mask the shift count to five bits, resulting in a maximum count of 31. This masking is done in all operating modes (including the virtual-8086 mode) to reduce the maximum execution time of the instructions Как я и предполагал выше: Intel так процы соптимизировал. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 27.01.2014, 16:32 |
|
||
|
Битовые сдвиги.
|
|||
|---|---|---|---|
|
#18+
Dimitry SibiryakovА оно проводится с учётом знаковости или без него? Т.к короткий тип всегда помещается в знаковый int, то расширенный тип будет знаковым. Касательно самих сдвигов - для положительных значений (независимо от того знаковый тип или нет) выполняется простой сдвиг с заполнением нулем. А для отрицательных значений, операция не описана стандартом и зависит от реализации. Насколько я знаю, на платформе x86 для знаковых (как положительных так и отрицательных) чисел выполняется арифметический сдвиг (с расширением старшего бита). А для беззнаковых - простой сдвиг. Вышеприведенные требования стандарта при этом обеспечиваются автоматически. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 27.01.2014, 17:05 |
|
||
|
Битовые сдвиги.
|
|||
|---|---|---|---|
|
#18+
Anatoly MoskovskyТ.к короткий тип всегда помещается в знаковый int Ну, тут не всегда конечно, но на практике всегда :) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 27.01.2014, 17:08 |
|
||
|
Битовые сдвиги.
|
|||
|---|---|---|---|
|
#18+
SashaMercuryДля операций над короткими типам, меньшими чем int (char, short, bool) проводится расширение разрядности (integral promotion) до размера int. И максимальный размер сдвига, для которого результат гарантирован стандартом, определяется размером int, а не размером конкретного короткого типа. Поэтому, к примеру, 8-битный char можно сдвигать вплоть до 31 (для x86). При этом для сдвига начиная с 8 и до 31 результат будет гарантированно 0, а больший сдвиг - неопределен. " Ну очень здоровский комментарий Почитай книгу Генри Уоррена - Алгоритмические трюки для программистов. Там описаны почти все фокусы с битами и численные методы на этих свойствах. Книга написана так что дефектов плавающей разрядности int нету или по крайней мере я с ними не сталкивался. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 27.01.2014, 17:58 |
|
||
|
|

start [/forum/topic.php?fid=57&msg=38535206&tid=2019733]: |
0ms |
get settings: |
8ms |
get forum list: |
10ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
60ms |
get topic data: |
9ms |
get forum data: |
2ms |
get page messages: |
47ms |
get tp. blocked users: |
1ms |
| others: | 12ms |
| total: | 155ms |

| 0 / 0 |
