Я не могу понять этот оператор сдвига (справочник по C#):
class MainClass1
{
static void Main()
{
int i = 1;
long lg = 1;
Console.WriteLine("0x{0:x}", i << 1);
Console.WriteLine("0x{0:x}", i << 33);
Console.WriteLine("0x{0:x}", lg << 33);
}
}
/*
Output:
0x2
0x2
0x200000000
*/
class MainClass2
{
static void Main()
{
int a = 1000;
a <<= 4;
Console.WriteLine(a);
}
}
/*
Output:
16000
*/





<< - оператор сдвига влево; это принимает двоичное представление значения и перемещает все биты на «n» позиций влево (кроме «mod», см. «1»), заполняя их нулями.
>> - оператор сдвига вправо; это делает почти противоположное (движение вправо), за исключением значений со знаком (то есть тех, которые могут быть отрицательными), он заполняется нулями для отрицательных значений.
1:
Оператор сдвига по существу "модифицирует" ширину данных. Значение int составляет 32 бита, поэтому сдвиг влево, равный 33 (в Int32), точно такой же, как сдвиг влево, равный 1. Вы не получаете всех нулей. long - это 64 бита, поэтому сдвиг влево на 33 дает другой ответ (исходное время 2 ^ 33).
2:
Каждый сдвиг влево (в пределах ширины данных) такой же (для целых чисел), что и x2, поэтому << 4 равно x2x2x2x2 = x16.
Это простой двоичный файл:
0000000001 = 1
<< переходит в
0000000010 = 2
<< переходит в
0000000100 = 4
<< переходит в
0000001000 = 8
Это все равно, что сказать «почему 1 * 50000 отличается от 1000 * 8» - потому что вы делаете очень разные вещи. Первый - 2 ^ 33 («степень»), второй - 1000 * 16.
хорошо, я понимаю разницу между 2 ^ 33 и 1000 * 16, я хочу знать, почему 2 ^ 32
33 - это int (2 ^ 5) теперь для перехода на long (2 ^ 6), почему 2 ^ 33? Спасибо
1 << 1 = 2 = равно 2 ^ 1; 1 << 2 = 4 = 2 ^ 2; 1 << 33 = ... = 2 ^ 33 (долго; не для int)
Спасибо. Я ищу формулу во втором, у меня a = 1000 << 4, 1000 равно 1111101000 в двоичном формате, ???????????????? Я не знаю, как вы находите 1000 * 16, могу я попросить вас дать мне формулу, чтобы лучше понять это?
как вы сказали в примере 1, у нас есть 3 выхода, выход 1 - 0x2, потому что оба они int. выход 2 снова равен 0x2, потому что 1 и 33 оба являются int. вывод 3 равен 0x200000000, потому что 1 длинный, а 33 - int, как вы сказали, это 2 ^ 33.
Итак, теперь для второго примера у нас есть 4 и 1000, что оба они int? почему 1000 * 16 ???? в чем разница между вторым примером и вторым выводом первого примера? Спасибо вам большое
Каждый сдвиг влево равен x2. Итак, 4 сдвига влево (<< 4) равны x2x2x2x2 = x16. Итак, 1000 << 4 = 1000 * 16 = 16000. С << 33 и int: 33% 32 = 1, поэтому << 33 то же самое, что << 1, а << 65 то же самое, что и << 1, as << 97. Только остаток div 32 важен с int. С long это остаток div 64.
Просто чтобы немного расширить ответ Марка (Марк, не стесняйтесь включать это в свой, и я удалю этот ответ), это указано в разделе 7.8 спецификации:
Предварительно определенные операторы сдвига перечислены ниже.
Сдвиг влево:
Оператор << сдвигает x влево на количество бит, вычисленное, как описано ниже.
Старшие биты вне диапазона типа результата x отбрасываются, оставшиеся биты сдвигаются влево, а позиции пустых битов младшего разряда устанавливаются на ноль.
Сдвиг вправо:
Оператор >> сдвигает x вправо на количество бит, вычисленное, как описано ниже.
Когда x имеет тип int или long, младшие биты x отбрасываются, оставшиеся биты сдвигаются вправо, а позиции пустых битов высокого порядка устанавливаются на ноль, если x неотрицательный, и на единицу, если x отрицательный.
Когда x имеет тип uint или ulong, младшие биты x отбрасываются, оставшиеся биты сдвигаются вправо, а позиции пустых битов высокого порядка устанавливаются в ноль.
Для предопределенных операторов количество сдвигаемых битов вычисляется следующим образом:
Когда тип x - int или uint, счетчик сдвига задается пятью младшими битами счетчика. Другими словами, количество сдвигов вычисляется из count & 0x1F.
Когда тип x длинный или ulong, счет сдвига задается шестью младшими битами счета. Другими словами, количество сдвигов вычисляется из count & 0x3F.
Если результирующий счетчик сдвига равен нулю, операторы сдвига просто возвращают значение x.
Еще несколько замечаний для начинающего программиста:
Зачем использовать операторы сдвига? Кажется, они мало что делают. На то есть 2 причины:
Они действительно быстрые, потому что почти все процессоры имеют регистры сдвига, что означает, что операция сдвига выполняется аппаратно с минимальными усилиями (циклами).
Поскольку они быстры, многие протоколы и стандарты разработаны для использования этого преимущества. Например, операции с IP-адресом, проверка CRC, графические операции и т. д.
«Оператор сдвига по сути« модифицирует »ширину данных».
Мусор! Если величина сдвига больше или равна ширине данных, результат не определен. Не ожидайте, что одна и та же операция «mod», которую вы случайно видели, произойдет с разными компиляторами или разными версиями одного и того же компилятора, или в разных ситуациях сдвига в одной и той же программе, или когда что-то еще изменится. Вот что означает «неопределенный».
Фактическая спецификация языка C# 4.0 гласит: 1) Когда тип x - int или uint, счетчик сдвига задается пятью младшими битами счетчика. Другими словами, количество сдвигов вычисляется из count & 0x1F. 2) Когда тип x длинный или ulong, счет сдвига задается шестью младшими битами счета. Другими словами, количество сдвигов вычисляется из count & 0x3F.
Привет, могу я попросить вас объяснить это поподробнее? В первом почему у меня 0x200000000, а во втором почему у меня 16000? Спасибо вам большое