Урок за изместване на битове в Java? [затворено]

Ще бъда благодарен за добър урок, който обяснява на начинаещите в Java как работи цялото „изместване на битове“ в Java.

Винаги се натъквам на него, но никога не разбирам как работи. Трябва да обясни всички операции и концепции, които са възможни с байтовото изместване/битова манипулация в java.

Това е само пример за това, което имам предвид (но търся урок, който обяснява всяка възможна операция):

byte b = (byte)(l >> (8 - i << 3));

person Markus    schedule 06.06.2011    source източник
comment
Това е битово изместване, а не байтово изместване.   -  person Oded    schedule 06.06.2011
comment
благодаря, актуализирах заглавието (ти беше по-бърз;-)   -  person Markus    schedule 06.06.2011
comment
Може да искате да разгледате тази страница: stackoverflow.com/questions/141525/   -  person Mike Kwan    schedule 06.06.2011
comment
За всички заинтересовани, освен отговорите по-долу, връзката от Майк по-горе абсолютно си струва да бъде прочетена!   -  person Markus    schedule 06.06.2011


Отговори (8)


Е, официалният урок по Java Побитови и побитови оператори за преместване обхваща действителни операции, които са налични в Java, и как да ги извикате.

Ако се чудите „какво мога да направя с преместването на битове“, тогава това не е специфично за Java и тъй като това е техника от ниско ниво, не знам за списък с „готини неща, които можете“ да правите сами по себе си. Струва си да се запознаете с дефинициите и да държите очите си отворени за друг код, където това се използва, за да видите какво са направили.

Имайте предвид, че често преместването на битове е печалба за ефективност за сметка на яснотата. Например a << 1 обикновено е същото като a * 2, но вероятно е по-малко ясно. Повтарящите се XOR могат да разменят две числа, без да се използва временна променлива, но обикновено се счита за по-добра форма кодът да се напише по-ясно с временната променлива (или дори по-добре, в полезен метод). Така че в това отношение е трудно да се дадат страхотни примери, защото е малко вероятно да постигнете нещо ново или задълбочено на ниво архитектура; всичко е свързано с детайлите на ниско ниво. (И бих преценил, че огромен брой употреби на превъртане на битове „в дивата природа“ са случаи на преждевременна оптимизация.)

person Andrzej Doyle    schedule 06.06.2011
comment
От друга страна, харесвам 1 << i повече от (int)Math.pow(2,i) (за i в диапазона 0 .. 31). - person Paŭlo Ebermann; 06.06.2011
comment
@Paŭlo: Всъщност това е добър пример за моята теза. Въпреки че Java е многословна, аз предпочитам Math.pow тук, защото декларира намерението. Фактът, че целите числа се изпълняват като двоични зад кулисите, прави аритметиката на степен на две изразима с по-малко знаци (и може би цикли на процесора), тъй като << е случайност на хардуера. Като цяло побитовите оператори трябва (IMHO) да се използват само когато обектът наистина е поредица от байтове и вие правите нещо като хеширане/крипто/компресия/и т.н. - в противен случай рискувате да създадете код само за запис. - person Andrzej Doyle; 06.06.2011
comment
Ако има оператор за степенуване на цяло число, аз също бих го предпочел. Но няма и Math.pow е дефиниран на double стойности. (И тъй като Java вече използва ^ за побитово/логическо XOR, няма да получим такъв оператор.) Мисля, че може да се разреши само 1 << i (може би с коментар // 2^i или такъв). - person Paŭlo Ebermann; 06.06.2011
comment
Побитовите операции са полезни за неща като RGB цветове, създадени от BufferedImages. - person Thijser; 06.02.2014
comment
Що се отнася до страхотните операции, най-удобната, която някога съм намирал, е размяната на XOR - тя ви позволява да превключвате стойностите на две променливи, без да се налага да отделяте повече памет. В Java би било X = X^Y; Y = Y^X; X = X^Y; Приложенията може да изглеждат ограничени, но ако имате работа с вградени системи с ограничения на паметта или искате сериозно да оптимизирате производителността, това има своето приложение. - person mdhansen; 06.04.2016

Когато използвате оператора shift, бъдете много внимателни да не повторите често срещана грешка!!

Както предлага следната SO публикация, авторът на приетия отговор споменава:

„В някои езици прилагането на операторите за смяна към всеки тип данни, по-малък от int, автоматично преоразмерява операнда, за да бъде int.“

Това е изключително важно да запомните, когато работите с байтове например, в противен случай може да получите неочаквани резултати (както направих аз).

Даден е байт със следния битов модел:

1001 0000

Когато се опитах да изместя малко с 4 и присвоих на int, като например:

int value = byteValue >>> 4;

Бих очаквал да имам:

0000 1001   (or a value of 9)

Но бих получил ОГРОМЕН брой! Това е така, защото byteValue се прехвърля към int ПРЕДИ операцията за изместване на битове, което води до нещо подобно вместо това:

1111 1111 1111 1111 1111 1111 1001
person Jeach    schedule 07.11.2012
comment
Хубаво решение за този проблем е създаването на битова маска (в този случай 0000 0000 0000 0000 0000 0000 1111) и &ing на резултата с маската, за да се принуди премахването на потенциални разширени водещи 1s. - person mdhansen; 06.04.2016

Има безкраен брой възможни комбинации. Те обаче ще бъдат съставени от една или повече комбинации от

>> shift right with sign extension.
>>> shift right with out sign extension.
<< shift left.

За да получите разбиране, ви предлагам да напишете двоичните числа на хартия и да разберете какво се случва. Опитът да го прочетете в урок няма да гарантира разбиране. особено ако не са помогнали досега.

person Peter Lawrey    schedule 06.06.2011

Има прост, но ясен урок, който намирам за полезен тук

person msb    schedule 06.06.2011
comment
Връзката вече не работи. - person eddyrokr; 27.08.2014

Не е точно урок, но имам личен библиотека с функции за преместване на битове в Java, която сте добре дошли да изучавате!

Освен това, ако потърсите в Google "битови трикове", ще намерите много материал. Много от тях са в C/C++, но обикновено е тривиално за конвертиране в Java, тъй като повечето от синтаксиса са еднакви.

person mikera    schedule 06.06.2011

Ето подробности за това как работи преместването на битове. Има известно неинтуитивно поведение, което не е обхванато от официалния урок. Например, десният операнд има ограничен диапазон (0-31 за int, 0-63 за long) и няма да изведе предупреждение, ако превишите този диапазон - той просто ще съкрати битовете (т.е. %32 или %64 ), което може да даде поведение, различно от очакваното.

person adam.r    schedule 21.08.2013

Този сайт изглежда дава доста добър урок за това какво можете да правите с битова манипулация (така че не е специфично за java, но тъй като е доста лесен за превод)

http://www.bogotobogo.com/cplusplus/quiz_bit_manipulation.html

Урокът по-горе предоставя

  • Побитови операции
  • Настройка и изчистване на малко
  • Показване на цяло число с битове
  • Преобразуване на десетична в шестнадесетична
  • Броят битове, зададени в цяло число (брой единици)
  • Позицията на набор от битове на цяло число
  • In-Place Integer Swap с битова манипулация
  • Броят битове, необходими за преобразуване на цяло число A в цяло число B
  • Разменете нечетни и четни битове в цяло число
  • Какво (n & (n-1) == 0) се проверява?
  • Допълнение на две
  • Обръщане на n-тия бит от цяло число
  • Битов модел на число с плаваща запетая
  • Палиндром на битов модел на цяло число

Ето един файл, който има куп реализации на Java

http://geekviewpoint.com/

person i8abug    schedule 28.09.2011

Това са два добри урока, които намерих, докато изучавах битовото изместване, те не са в java, но повечето езици използват едни и същи оператори и теорията е същата.

  1. Извъртане на битове
  2. PHP Bitwise урок от Джим Плюш
person mike    schedule 20.02.2012