Почему отрицание значения меняет результат при 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

просмотрите представления битов для целых чисел и чисел с плавающей запятой для получения дополнительной информации.