2016-05-10 16 views
2

Basierend auf dem, was ich über the binary representation of integers gelesen habe, ist das erste Bit für das Vorzeichen (positiv oder negativ).Was ist eine gute Möglichkeit, eine Ganzzahl in binärer Operation in Python zu negieren?

Nehmen wir an, wir haben eine ganze Zahl x = 5 und sys.getsizeof(x) gibt 28 zurück (das ist binäre Darstellung in 28 Bit).

Für jetzt versuche ich das erste Bit zu 1 mit x|=(1<<27) zu wenden, aber es gibt 134217733 zurück.

Ich habe mich nur gefragt, ob es eine negative Zahl sein muss? (nicht -5)

Ist etwas falsch mit dem was ich mache?

+0

Wenn man bedenkt, dass 'bin (5)' '' 0b101'' zurückgibt, welches Bit möchten Sie umdrehen? –

+2

Beachten Sie auch, dass sys.getsizeof (x) die Größe in Bytes und nicht in Bits zurückgibt. – Schore

+0

Ich möchte nur das Vorzeichen Bit (um es negative Zahl machen) – Hypnoz

Antwort

2

Sie können keinen Python wechseln int von positiv auf negativ den Weg zu Sie versuchen, nur um ein wenig in seiner Darstellung Spiegel. Sie nehmen an, dass es in einer Zweierkomplementdarstellung fester Länge gespeichert ist. Aber Integer in Python 3 sind keine Bitfolgen fester Länge, und sie werden nicht in einer Zweierkomplementdarstellung gespeichert. Stattdessen werden sie als Strings mit variabler Länge von 30- oder 15-Bit- "Ziffern" gespeichert, wobei das Zeichen separat gespeichert wird (z. B. signed-magnitude representation). Also die "niedrigste" Möglichkeit, ein Python int zu negieren, ist nicht mit Bit-Operationen, sondern mit dem unären --Operator, der sein Vorzeichen wechselt. (Siehe Ende dieser Antwort für Details aus der Python-3-Quelle.)

(Ich sollte auch erwähnen, dass sys.getsizeof() tut nicht Ihnen sagen, die Anzahl der Bits in Ihrem int. Es gibt Ihnen die Anzahl von Bytes des Speichers ., dass die integer-Objekt wird mit diesem auch nicht die Anzahl der Bytes der tatsächlichen gespeicherten Nummer ist, die meisten dieser Bytes sind für andere Dinge)


Sie noch mit Zweierkomplement-Darstellungen in Python rumspielen kann. durch Emulieren einer Bitfolge fester Länge unter Verwendung einer positiven int. Wählen Sie zunächst die gewünschte Länge aus, z. B. 6 Bits. (Sie können nur wählen, wie leicht größere Zahlen wie 28 oder 594.) Wir können einige hilfreiche Konstanten und Funktionen definieren:

BIT_LEN = 6 
NUM_INTS = 1 << BIT_LEN   # 0b1000000 
BIT_MASK = NUM_INTS - 1   # 0b111111 
HIGH_BIT = 1 << (BIT_LEN - 1) # 0b100000 

def to2c(num): 
    """Returns the two's complement representation for a signed integer.""" 
    return num & BIT_MASK 

def from2c(bits): 
    """Returns the signed integer for a two's complement representation.""" 
    bits &= BIT_MASK 
    if bits & HIGH_BIT: 
     return bits - NUM_INTS 

Jetzt können wir etwas tun, wie Sie versuchen zu:

>>> x = to2c(2) 
>>> x |= 1 << 5 
>>> bin(x) 
'0b100010' 
>>> from2c(x) 
-30 

Welche zeigt, dass das Einschalten des High-Bits für die Zahl 2 in einer 6-Bit-Zweierkomplementdarstellung die Zahl in -30 umwandelt.Dies macht Sinn, denn 2 6-1 = 32, also ist die niedrigste ganze Zahl in dieser Darstellung -32. Und -32 + 2 = -30.


Wenn Sie in den Details interessiert sind, wie Python 3 speichert ganze Zahlen Sie durch Objects/longobject.c in der Quelle suchen. Insbesondere Blick auf the function _PyLong_Negate():

/* If a freshly-allocated int is already shared, it must 
    be a small integer, so negating it must go to PyLong_FromLong */ 
Py_LOCAL_INLINE(void) 
_PyLong_Negate(PyLongObject **x_p) 
{ 
    PyLongObject *x; 

    x = (PyLongObject *)*x_p; 
    if (Py_REFCNT(x) == 1) { 
     Py_SIZE(x) = -Py_SIZE(x); 
     return; 
    } 

    *x_p = (PyLongObject *)PyLong_FromLong(-MEDIUM_VALUE(x)); 
    Py_DECREF(x); 
} 

Sie können sehen, dass alle es im Normalfall macht, ist die Py_SIZE() Wert des ganzzahligen Objekt negieren. Py_SIZE() ist einfach eine Referenz auf das Feld ob_size des Integer-Objekts. Wenn dieser Wert 0 ist, ist die Ganzzahl 0. Andernfalls ist das Vorzeichen das Vorzeichen der Ganzzahl und der absolute Wert ist die Anzahl der 30- oder 15-Bit-Ziffern im Array, die den absoluten Wert der Ganzzahl enthalten.

0

Negative Zahlendarstellungen in Python:

Je nachdem, wie viele binary digit Sie wollen, subtrahieren von einer Zahl (2 n):

>>> bin((1 << 8) - 1) 
'0b11111111' 
>>> bin((1 << 16) - 1) 
'0b1111111111111111' 
>>> bin((1 << 32) - 1) 
'0b11111111111111111111111111111111' 

Funktion Zweier-Komplementen (negativ zu erzeugen Nummer):

def to_twoscomplement(bits, value): 
    if value < 0: 
     value = (1<<bits) + value 
    formatstring = '{:0%ib}' % bits 
    return formatstring.format(value) 

Ausgabe:

>>> to_twoscomplement(16, 3) 
'0000000000000011' 
>>> to_twoscomplement(16, -3) 
'1111111111111101' 

Siehe: two's complement of numbers in python

Verwandte Themen