Ответ 1
См. два дополнения для представления отрицательных целых чисел на многих языках. Как вы можете видеть, -2 представлен 1111110
; если вы инвертируете все эти биты, вы получаете 0000001
, то есть значение 1.
Почему битовый оператор NOT (~
в большинстве языков) преобразует следующие значения:
-2 -> 1
-1 -> 0
0 -> -1
1 -> -2
Не следует -2
конвертировать в 2
, 1
преобразовать в -1
и т.д.?
См. два дополнения для представления отрицательных целых чисел на многих языках. Как вы можете видеть, -2 представлен 1111110
; если вы инвертируете все эти биты, вы получаете 0000001
, то есть значение 1.
Это помогает, если вы посмотрите на него в двоичном формате.
Прежде всего, как вы знаете, отрицательные числа выражаются как (максимально возможное беззнаковое число плюс 1 минус значение). Таким образом, -1 в 16-битовом целое, которое имеет наивысшее значение без знака 65535, будет 65536-1 = 65535, то есть 0xffff в шестнадцатеричном выражении или 1111 1111 1111 1111
в двоичном формате.
Итак:
1 в двоичном формате = 0000 0000 0000 0001
НЕ для всех бит приведет к 1111 1111 1111 1110
. То, что в десятичной системе, равно 65534. А 65536 минус 65535 равно 1, поэтому это -1.
Большинство (все?) современных архитектур используют два дополнения для представления целых чисел. Таким образом, побитовое NOT представляет собой дополнение целого числа минус единицы.
Это связано с тем, что отрицательные числа представлены как биты. Для этого обычно используется Two Complements.
-2 в этом обозначении 1111110, которое отрицает 1
Это связано с тем, что бит-мудрый оператор буквально инвертирует каждый бит в слове. Это НЕ строго арифметическая операция, это логическая операция.
-2 ==% 1110, ~ -2 == ~% 1110 =% 0001 == 1 -1 ==% 1111, ~ -1 == ~% 1111 =% 0000 == 0
и т.д.
Чтобы перейти от -2 к 2 и от 1 до -1, вам нужно использовать операцию арифметического отрицания.
Dim mask As Integer = -1
'11111111111111111111111111111111
For x As Integer = -3 To 3
Dim i As Integer = x
Debug.WriteLine("")
Debug.WriteLine("'" & Convert.ToString(i, 2).PadLeft(32, "0"c) & " > Num = " & i.ToString)
i = i Xor mask 'reverse the bits (same as Not)
Debug.WriteLine("'" & Convert.ToString(i, 2).PadLeft(32, "0"c) & " > Not = " & i.ToString)
i += 1 'convert to two complement
Debug.WriteLine("'" & Convert.ToString(i, 2).PadLeft(32, "0"c) & " > 2 Comp = " & i.ToString)
Next
'debug results
'11111111111111111111111111111101 > Num = -3
'00000000000000000000000000000010 > Not = 2
'00000000000000000000000000000011 > 2 Comp = 3
'11111111111111111111111111111110 > Num = -2
'00000000000000000000000000000001 > Not = 1
'00000000000000000000000000000010 > 2 Comp = 2
'11111111111111111111111111111111 > Num = -1
'00000000000000000000000000000000 > Not = 0
'00000000000000000000000000000001 > 2 Comp = 1
'00000000000000000000000000000000 > Num = 0
'11111111111111111111111111111111 > Not = -1
'00000000000000000000000000000000 > 2 Comp = 0
'00000000000000000000000000000001 > Num = 1
'11111111111111111111111111111110 > Not = -2
'11111111111111111111111111111111 > 2 Comp = -1
'00000000000000000000000000000010 > Num = 2
'11111111111111111111111111111101 > Not = -3
'11111111111111111111111111111110 > 2 Comp = -2
'00000000000000000000000000000011 > Num = 3
'11111111111111111111111111111100 > Not = -4
'11111111111111111111111111111101 > 2 Comp = -3