Почему нам нужно использовать операторы shift в java?
какова цель использования операторов сдвига вместо деления и умножения?
существуют ли другие преимущества использования операторов сдвига?
где следует попытаться использовать оператор shift?
6 ответов
деление и умножение не действительно использование операторов битового сдвига. Это устаревшая "оптимизация", которую некоторые любят применять.
они являются битовыми операциями и полностью необходимы при работе на уровне битов в пределах целого значения.
например, скажем, у меня есть два байта, которые являются байтами высокого и низкого порядка двухбайтового (16-битного) значения без знака. Скажем, вам нужно построить это значение. в Java, это:
int high = ...;
int low = ...;
int twoByteValue = (high << 8) | low;
вы не могли бы иначе сделать это без оператора shift.
чтобы ответить на ваши вопросы: вы используете их, когда вам нужно использовать их! и больше нигде.
оператор shift используется при выполнении логическое операции с битами, в отличие от математическое операции.
Это can используется для скорости, будучи значительно быстрее, чем деление / умножение при работе с операндами, которые являются степенями двух, но ясность кода обычно предпочтительнее сырой скорости.
Он также может использоваться в шифрования/дешифрования .. Образец: http://freedom2blog.com/2010/05/easy-encryption-using-bitwise-exclusive-or-xor/
это полезно при построении значений, которые представляют собой комбинацию чисел, где биты сгруппированы как разные значения. (Ответ Шона Оуэна объясняет это лучше.)
например, работа с цветами, которые являются:
-
"#AARRGGBB"
как строка base16 -
0xAAAARRRRGGGGBBBB
как целое число
в его целочисленном формате вы можете использовать shift для получения фактического значения компонента целого числа в качестве полезного числа.
public static int stringToColor(String s) throws JSExn {
// string starts with '#' - parse integer from string
try {
// used to build up the return value
int a, r, g, b;
switch (s.length()) {
case 4:
a = 0xFF000000;
r = Integer.parseInt(s.substring(1, 2), 16);
r = r << 16 | r << 20;
b = Integer.parseInt(s.substring(2, 3), 16);
b = b << 8 | b << 12;
g = Integer.parseInt(s.substring(3, 4), 16);
g = g | g << 4;
break;
case 5:
a = Integer.parseInt(s.substring(1, 2), 16);
a = a << 24 | a << 28;
r = Integer.parseInt(s.substring(2, 3), 16);
r = r << 16 | r << 20;
b = Integer.parseInt(s.substring(3, 4), 16);
b = b << 8 | b << 12;
g = Integer.parseInt(s.substring(4, 5), 16);
g = g | g << 4;
break;
case 7:
a = 0xFF000000;
r = Integer.parseInt(s.substring(1, 3), 16) << 16;
b = Integer.parseInt(s.substring(3, 5), 16) << 8;
g = Integer.parseInt(s.substring(5, 7), 16);
break;
case 9:
a = Integer.parseInt(s.substring(1, 3), 16) << 24;
r = Integer.parseInt(s.substring(3, 5), 16) << 16;
b = Integer.parseInt(s.substring(5, 7), 16) << 8;
g = Integer.parseInt(s.substring(7, 9), 16);
break;
default:
throw new JSExn("Not a valid color: '"+s+"'");
}
// return our integer ARGB
return a | r | b | g;
}
снижение прочности происходит, когда операция заменяется эквивалентной операцией, которая выполняется быстрее.
- замена целочисленного деления или умножения на степень 2 с арифметическим сдвигом или логическим сдвигом..
- замена целочисленного умножения на константу комбинацией сдвигов, добавлений или вычитаний.
- замена целочисленного деления на константу с умножением, используя ограниченный диапазон машин целое число.
Почему это неправильно?
1.Уменьшает производительность по мере увеличения времени, необходимого для расчета. 2. Арифметические операции, такие как деление и умножение медленнее. 3. Дорогие операции
преимущества
- повышает производительность.
- более быстрые вычисления.
выговор
- читаемость кода уменьшается.
это полезно, когда вы имеете дело с флагами, можно хранить в одном int
переменная информация об активных флагах, см. Следующие пожалуйста:
public class DealingWithShiftOperators {
public static void main(String[] args) {
int active_flags = 10;
printActiveFlags(active_flags);
}
public static void printActiveFlags(int active_flags) {
final int TOTAL_FLAGS = 8;
final int MAX_VALUE = 1 << TOTAL_FLAGS;
final int MIN_VALUE = 1;
int current_flag = MAX_VALUE;
do {
current_flag = current_flag >> 1;
if (active_flags - current_flag < 0) {
System.out.println(current_flag + ": off");
} else {
active_flags = active_flags - current_flag;
System.out.println(current_flag + ": on");
}
} while (current_flag > MIN_VALUE);
}
}
в приведенном выше примере выводится следующее:
128: off
64: off
32: off
16: off
8: on
4: off
2: on
1: off
Как видите,active_flags
- номер 2 и номер 8. Мы сохранили эту информацию только в одной переменной, ее значение равно 10 (8+2).