Почему отрицание значения меняет результат при XORing с 1?
Я знаю работу XOR,
Console.WriteLine(1^1); // returns 0
результат
00000001
00000001
--------
00000000
но как это возвращает 2?
Console.WriteLine(-(-1^1)); // returns 2
Ответы
Ответ 1
-1 сохраняется как значение со всеми битами, установленными в 1. Если мы остаемся на вашем примере с 8 битами, тогда -1 будет равно 11111111. Таким образом, -1^1
дает следующее:
11111111
00000001
--------
11111110
Который равен -2. Когда вы инвертируете его с другим минусом, вы получаете 2.
Отрицательные числа сохраняются так, как мы называем два дополнения номера. Если вы хотите быстро вычислить его в своей голове, вы можете просто перевернуть все биты положительного эквивалента вашего номера и добавить его к нему. Итак, для -1:
1: 00000001
--------
11111110
+ 1
--------
-1: 11111111
Объяснение, почему -1 хранится как 11111111.
Если вы хотите понять два дополнения немного больше, этот вопрос также может помочь вам.
Ответ 2
Это выражение интерпретируется компилятором как:
-((-1)^1)
который:
- ((11111111) XOR (00000001)) = - (11111110) = - (-2) = 2
Чтобы понять, почему компилятор выбирает -((-1)^1)
вместо -(-(1^1))
, посмотрите эту статью о приоритете операторов С#. Наиболее важным является то, что унарный оператор -
(полужирный: - ( - 1 ^ 1)) имеет более высокий приоритет, чем оператор XOR ^
. Поэтому отрицание происходит до XOR, и мы получаем -((-1)^1)
.
Я использую здесь 8 бит на целое число. Обычно вы должны ожидать 32 или 64 бита на номер, но в этом случае это не имеет значения;
Чтобы лучше понять, почему 11111111 равно -1, а 11111110 равно -2, читайте больше о двух дополнениях - https://en.wikipedia.org/wiki/Two%27s_complement. Короче говоря, вы обрабатываете все биты отдельно от самых левых, как последовательные степени 2. Самый левый бит рассматривается как следующий, но отрицательный.
Пример:
10001100 = 1 * (-(2^7)) + 0 * 2^6 + 0 * 2^5 + 0 * 2^4 + 1*2^3 + 1*2^2 + 1*2^1 + 1*2^0
Ответ 3
Отрицательные числа представлены в виде двоичного дополнения, т.е.
-x == ~x + 1
Итак, мы имеем
-(-1 ^ 1) ==
-(0b11111...1111 ^ 1) ==
-(0b11111...1110) ==
2
Ответ 4
Я предполагаю подписанный Int32
s.
-1 11111111111111111111111111111111 (two complement)
1 00000000000000000000000000000001
-----------------------------------------
-1^1 11111111111111111111111111111110
-(-1^1) 00000000000000000000000000000010 --> 2
См. приоритет оператора С# и два дополнения.
Ответ 5
В двоичном формате с использованием двух дополнений;
11111111^00000001=11111110
.
Двоичное два дополнения 11111110
является десятичным -2
.
Ответ 6
-1
11111111
(для этого проверьте два дополнения)
когда вы создаете xor с 1
, который есть 00000001
, у вас есть:
11111110
, который равен -2
(снова два дополнения)
Чтобы понять два дополнения (математика может быть довольно абстрактной), вот что я имею в виду:
0
= 00...00
1
= 00...001
...
max - 1
= 011...110
max
= 011...11
min
= 100...00
min + 1
= 100...001
...
-1
= 11...11
Очевидно, что min
и max
зависят от количества бит, которое вы используете для представления целых чисел
Ответ 7
int имеет 32 бита.
-1 равно 1111 1111 1111 1111 1111 1111 1111 1111
1 равно 0000 0000 0000 0000 0000 0000 0000 0001
поэтому -1 ^ 1 равно 1111 1111 1111 1111 1111 1111 1111 1110
, равному -2
so (- (- 1 ^ 1)) = 2
просмотрите представления битов для целых чисел и чисел с плавающей запятой для получения дополнительной информации.