Почему ~ True приводит к -2?

132

В консоли Python:

~True

Дает мне:

-2

Зачем? Может кто-нибудь объяснить мне этот конкретный случай в двоичном виде?

lukaszkups
источник
22
потому что ~1есть -2, попробуйте:True == 1
Grijesh Chauhan
15
Чтобы быть точным: это неправда, что " True is 1", но это правда True == 1.
Бах
3
Вы действительно думаете, что просмотр UNARY_INVERT(всего байт-кода) что-то добавит к ответам?
Wooble
2
Этот вопрос не повторяется! Он спрашивает о конкретном поведении bool. Дело не в том, как ~работает. Фактически, правильный ответ на этот вопрос мог бы избежать упоминания дополнения 2 и того, как ~вообще работает с целыми числами.
Bakuriu

Ответы:

240

int(True)есть 1.

1 является:

00000001

и ~1это:

11111110

Что находится -2в дополнении до двух 1

1 Переверните все биты, добавьте 1 к полученному числу и интерпретируйте результат как двоичное представление величины и добавьте отрицательный знак (поскольку число начинается с 1):

11111110  00000001  00000010 
                    
       Flip       Add 1

Это 2, но знак отрицательный, так как MSB равен 1.


Стоит отметить:

Подумайте bool, вы обнаружите, что он числовой по своей природе - он имеет два значения, Trueи False, и они просто «настроенные» версии целых чисел 1 и 0, которые только печатают себя по-разному. Это подклассы целочисленного типа int.

Таким образом, они ведут себя точно так же, как 1 и 0, за исключением того, что boolпереопределяют strи reprотображают их по-разному.

>>> type(True)
<class 'bool'>
>>> isinstance(True, int)
True

>>> True == 1
True
>>> True is 1  # they're still different objects
False
Марун
источник
1
@ofcapl Просто хотел сказать: хотя int('1')это тоже, 1но ~'1'это исключение typeerror, тогда как ~Trueэто не так, потому boolчто подкласс int@ Martijn добавил эту информацию в свой ответ.
Grijesh Chauhan
Для записи @ofcapl этот ответ показывает двоичную арифметическую интерпретацию происходящего, а не фактический байт-код (который был бы своего рода кодом промежуточного уровня или уровня операции, скомпилированным из источника).
Patrick M
5
@etrusco, о каких языках ты говоришь? Я точно знаю 0 где True == -1, и я знаю многих, где это можно было сказать True == 1...
l4mpi
1
@etrusco @ l4mpi В некоторых БЕЙСИКах старой школы используется -1ИСТИНА; у него есть приятное свойство, что побитовые операторы И и ИЛИ работают также и для логических И и ИЛИ ( x & -1ненулевые в тех же случаях, что x && 1ненулевые в С), если вы не заботитесь о коротком замыкании , Однако, насколько мне известно, ни один из основных языков никогда не использовался -1для ИСТИНЫ.
Quuxplusone
1
Формальная логика определяет truthкак однозначное; со всем , что не trueявляется false. Все языки программирования, о которых я знаю, переворачивают формальную логику с falseног на голову, определяя как однозначное (0) и все, что не является ложным true). Например, C # , хотя Javascript является чем-то особенным, имеющим несколько оттенков правдивости и несколько оттенков лжи .
Николас Кэри
45

Тип Python boolявляется подклассом int(по историческим причинам; логические значения были добавлены только в Python 2.3).

Так как int(True)это 1, ~Trueэто ~1есть -2.

См. PEP 285, чтобы узнать, почему boolявляется подклассом int.

Если вам нужна логическая инверсия, используйте not:

>>> not True
False
>>> not False
True

Если вы хотите знать, почему ~1это так -2, то это потому, что вы инвертируете все биты в целое число со знаком ; 00000001становится, 1111110которое в знаковом целом числе является отрицательным числом, см . Дополнение до двух :

>>> # Python 3
...
>>> import struct
>>> format(struct.pack('b', 1)[0], '08b')
'00000001'
>>> format(struct.pack('b', ~1)[0], '08b')
'11111110'

где начальный 1бит означает, что значение отрицательное, а остальные биты кодируют обратное положительное число минус один.

Мартейн Питерс
источник
1
@GrijeshChauhan: Для двух комплиментов вы можете использовать struct.pack, as bin(integer)или format(integer, '08b')не учитывать целые числа со знаком .
Мартин Питерс
@thefourtheye, MartijnPieters я пытался , но это сбивает с толку , например bin(~True), bin(-2), bin(~1)все дает '-0b10' Если -2представление , 10то почему -знак.
Грижеш Чаухан
Что я имею в виду 102'комплемента тогда -ве?
Грижеш Чаухан
1
@GrijeshChauhan Вы можете получить два дополнения как отрицательных, так и положительных чисел, как этоformat(-2 % (1 << 32), "032b")
thefourtheye
2
@thefourtheye: Я бы использовал битовую маску:format(-2 & ((1 << 32) - 1), "032b")
Martijn Pieters
4

~True == -2это не удивительно , если True средство1 и ~ средства побитовое обращение ...

... при условии, что


Редактирование:

  • исправлено смешение между целочисленным представлением и оператором побитового обращения
  • применил еще одну полировку (чем короче сообщение, тем больше требуется работы)
волк
источник
2
~не означает "дополнение до двух". ~означает «Побитовая инверсия»
Маккей
1
Фраза «дополнение к одному» на самом деле не относится к операции, так как она относится к системе хранения целых чисел в битах. Система, которая фактически не используется в компьютерной системе.
McKay