Der Integer-Typ von Python hat eine unbegrenzte Genauigkeit und ist nicht von den zugrunde liegenden Typen mit fester Größe abhängig. Daher kann nicht zwischen vorzeichenlosen und vorzeichenbehafteten Typen unterschieden werden. Sie müssen die Konvertierung selbst durchführen.
Poke
4
@AliSAIDOMAR nein, die absFunktion gibt nicht an, was die (unsigned)Besetzung in C gibt, was (uint32_t)a = (1LL << 32) - afür das Komplement von 2 ist
phuclv
Antworten:
95
Angenommen :
Sie haben 2-Komplement-Darstellungen im Sinn; und,
Damit meinen(unsigned long) Sie eine vorzeichenlose 32-Bit-Ganzzahl.
dann müssen Sie nur noch 2**32 (or 1 << 32)den negativen Wert addieren .
Annahme Nr. 1 bedeutet, dass -1 als feste Zeichenfolge mit 1 Bit angezeigt werden soll, und Annahme Nr. 2 bedeutet, dass Sie 32 davon wünschen.
Niemand außer Ihnen kann jedoch sagen, was Ihre verborgenen Annahmen sind. Wenn Sie beispielsweise 1-Komplement-Darstellungen im Auge haben, müssen Sie ~stattdessen den Präfix-Operator anwenden . Python-Ganzzahlen arbeiten hart, um die Illusion zu vermitteln, eine unendlich breite 2er-Komplementdarstellung zu verwenden (wie das reguläre 2er-Komplement, jedoch mit einer unendlichen Anzahl von "Vorzeichenbits").
Und um zu duplizieren, was der Plattform-C-Compiler tut, können Sie das ctypesModul verwenden:
>>> import ctypes
>>> ctypes.c_ulong(-1) # stuff Python's -1 into a C unsigned long
c_ulong(4294967295L)
>>> _.value
4294967295L
Cs sind unsigned longzufällig 4 Bytes in der Box, in der dieses Beispiel ausgeführt wurde.
Ich wusste nicht, dass Sie _sich auf das Ergebnis der vorherigen Zeile beziehen können!
Yay295
@ Yay295 Richtig! Ist dies nur im interaktiven Modus möglich oder kann es auch im nicht interaktiven Modus verwendet werden?
HelloGoodbye
1
@HelloGoodbye, "_"das Abrufen eines vorherigen Ergebnisses ist keine Funktion der Sprache selbst, sondern eine Annehmlichkeit, die von einigen (fast allen) interaktiven Python-Shells implementiert wird. Sie müssen unabhängig davon das aktuellste Ergebnis abrufen, um es anzuzeigen. Die Sprache selbst macht so etwas nicht.
Tim Peters
67
Um den Wert zu erhalten, der Ihrem C-Cast entspricht, nur bitweise und mit der entsprechenden Maske. zB wenn unsigned long32 Bit ist:
>>> i = -6884376>>> i & 0xffffffff4288082920
oder wenn es 64 Bit ist:
>>> i & 0xffffffffffffffff18446744073702667240
Beachten Sie jedoch, dass dies zwar den Wert ergibt, den Sie in C haben würden, es sich jedoch immer noch um einen vorzeichenbehafteten Wert handelt. Daher können nachfolgende Berechnungen zu einem negativen Ergebnis führen und Sie müssen die Maske weiterhin anwenden, um eine 32 oder 64 zu simulieren Bitberechnung.
Dies funktioniert, da Python zwar alle Zahlen als Vorzeichen und Größe speichert, die bitweisen Operationen jedoch so definiert sind, dass sie an den Zweierkomplementwerten arbeiten. C speichert ganze Zahlen in Zweierkomplement, jedoch mit einer festen Anzahl von Bits. Bitweise Python-Operatoren wirken auf Zweierkomplementwerte, aber als hätten sie eine unendliche Anzahl von Bits: Bei positiven Zahlen erstrecken sie sich mit Nullen nach links bis unendlich, negative Zahlen mit Einsen nach links. Der &Operator ändert diese linke Einsenfolge in Nullen und lässt Ihnen nur die Bits übrig, die in den C-Wert passen würden.
Das Anzeigen der Werte in hexadezimaler Darstellung kann dies klarer machen (und ich habe die Zeichenfolge von f als Ausdruck umgeschrieben, um zu zeigen, dass wir an 32 oder 64 Bit interessiert sind):
Bei einem 32-Bit-Wert in C steigen positive Zahlen auf 2147483647 (0x7fffffff), und bei negativen Zahlen wird das oberste Bit von -1 (0xffffffff) auf -2147483648 (0x80000000) gesetzt. Für Werte, die vollständig in die Maske passen, können wir den Prozess in Python umkehren, indem wir eine kleinere Maske verwenden, um das Vorzeichenbit zu entfernen und dann das Vorzeichenbit zu subtrahieren:
>>> u = i & ((1 << 32) - 1)
>>> (u & ((1 << 31) - 1)) - (u & (1 << 31))
-6884376
Oder für die 64-Bit-Version:
>>> u = 18446744073702667240>>> (u & ((1 << 63) - 1)) - (u & (1 << 63))
-6884376
Dieser inverse Prozess lässt den Wert unverändert, wenn das Vorzeichenbit 0 ist, aber offensichtlich ist es keine echte Inverse, denn wenn Sie mit einem Wert begonnen haben, der nicht in die Maskengröße passt, sind diese Bits weg.
Warum um alles in der Welt funktioniert das? (und was wäre die inverse Operation)
MB.
2
@ MB Ich habe meine Antwort erweitert, hoffe das hilft.
Duncan
Die Umkehrung hat sich als sehr nützlich erwiesen. Einige in C geschriebene Python-Bibliotheken geben einen vorzeichenbehafteten 64-Bit-Wert zurück, und dies endet als Long in Python
user1978816
16
Python hat keine vorzeichenlosen Typen eingebaut. Sie können mathematische Operationen verwenden, um ein neues int zu berechnen, das den Wert darstellt, den Sie in C erhalten würden, aber es gibt keinen "vorzeichenlosen Wert" eines Python-int. Das Python-Int ist eine Abstraktion eines ganzzahligen Werts, kein direkter Zugriff auf eine Ganzzahl mit fester Byte-Größe.
Sie können die in structPython integrierte Bibliothek verwenden:
Kodieren:
import struct
i = -6884376
print('{0:b}'.format(i))
packed = struct.pack('>l', i) # Packing a long number.
unpacked = struct.unpack('>L', packed)[0] # Unpacking a packed long number to unsigned long
print(unpacked)
print('{0:b}'.format(unpacked))
dec_pack = struct.pack('>L', unpacked) # Packing an unsigned long number.
dec_unpack = struct.unpack('>l', dec_pack)[0] # Unpacking a packed unsigned long number to long (revert action).
print(dec_unpack)
Aus:
-6884376
[ HINWEIS ]:
> ist BigEndian Operation.
l ist lang.
L ist lange nicht signiert.
In amd64Architektur intund longsind 32 - Bit, also Sie nutzen könnten iund Istatt lund Lsind.
Ich denke, das ist nur teilweise wahr. Wie im Python-MDN angegeben > abs() Gibt den absoluten Wert einer Zahl zurück. Das Argument kann eine einfache oder lange Ganzzahl oder eine Gleitkommazahl sein. Wenn das Argument eine komplexe Zahl ist, wird seine Größe zurückgegeben. Dies gibt per Definition nicht immer eine unsignedVariable zurück
Samuel Hulla
aber er bat nur um eine ganze Zahl.
Hari Prasath
1
Python verfügt nicht über eine integrierte Funktion zum Konvertieren von int in unsigned int. Stattdessen hat es eine lange Reichweite.
>>> val = 9223372036854775807 (maximum value of int 64)
>>> type(val)
<type 'int'>
>>> val += 1>>> type(val)
<type 'long'>
Durch Erhöhen des Werts von val um 1 überschreite ich die Grenze einer vorzeichenbehafteten 64-Bit-Ganzzahl und der Wert wird in eine lange konvertiert. Wenn Python eine vorzeichenlose Ganzzahl verwendet oder konvertiert hätte, wäre val immer noch ein int gewesen. Oder nicht lange.
Vorzeichenbehaftete Ganzzahlen werden durch ein Bit dargestellt, normalerweise das höchstwertige Bit, das für positive Zahlen auf 0 oder für negative Zahlen auf 1 gesetzt wird. Was val & 0xff tut, ist tatsächlich val & 0x000000ff (auf einem 32-Bit-Computer). Mit anderen Worten wird das vorzeichenbehaftete Bit auf 0 gesetzt und ein vorzeichenloser Wert emuliert.
abs
Funktion gibt nicht an, was die(unsigned)
Besetzung in C gibt, was(uint32_t)a = (1LL << 32) - a
für das Komplement von 2 istAntworten:
Angenommen :
(unsigned long)
Sie eine vorzeichenlose 32-Bit-Ganzzahl.dann müssen Sie nur noch
2**32 (or 1 << 32)
den negativen Wert addieren .Wenden Sie dies beispielsweise auf -1 an:
>>> -1 -1 >>> _ + 2**32 4294967295L >>> bin(_) '0b11111111111111111111111111111111'
Annahme Nr. 1 bedeutet, dass -1 als feste Zeichenfolge mit 1 Bit angezeigt werden soll, und Annahme Nr. 2 bedeutet, dass Sie 32 davon wünschen.
Niemand außer Ihnen kann jedoch sagen, was Ihre verborgenen Annahmen sind. Wenn Sie beispielsweise 1-Komplement-Darstellungen im Auge haben, müssen Sie
~
stattdessen den Präfix-Operator anwenden . Python-Ganzzahlen arbeiten hart, um die Illusion zu vermitteln, eine unendlich breite 2er-Komplementdarstellung zu verwenden (wie das reguläre 2er-Komplement, jedoch mit einer unendlichen Anzahl von "Vorzeichenbits").Und um zu duplizieren, was der Plattform-C-Compiler tut, können Sie das
ctypes
Modul verwenden:>>> import ctypes >>> ctypes.c_ulong(-1) # stuff Python's -1 into a C unsigned long c_ulong(4294967295L) >>> _.value 4294967295L
Cs sind
unsigned long
zufällig 4 Bytes in der Box, in der dieses Beispiel ausgeführt wurde.quelle
_
sich auf das Ergebnis der vorherigen Zeile beziehen können!"_"
das Abrufen eines vorherigen Ergebnisses ist keine Funktion der Sprache selbst, sondern eine Annehmlichkeit, die von einigen (fast allen) interaktiven Python-Shells implementiert wird. Sie müssen unabhängig davon das aktuellste Ergebnis abrufen, um es anzuzeigen. Die Sprache selbst macht so etwas nicht.Um den Wert zu erhalten, der Ihrem C-Cast entspricht, nur bitweise und mit der entsprechenden Maske. zB wenn
unsigned long
32 Bit ist:>>> i = -6884376 >>> i & 0xffffffff 4288082920
oder wenn es 64 Bit ist:
>>> i & 0xffffffffffffffff 18446744073702667240
Beachten Sie jedoch, dass dies zwar den Wert ergibt, den Sie in C haben würden, es sich jedoch immer noch um einen vorzeichenbehafteten Wert handelt. Daher können nachfolgende Berechnungen zu einem negativen Ergebnis führen und Sie müssen die Maske weiterhin anwenden, um eine 32 oder 64 zu simulieren Bitberechnung.
Dies funktioniert, da Python zwar alle Zahlen als Vorzeichen und Größe speichert, die bitweisen Operationen jedoch so definiert sind, dass sie an den Zweierkomplementwerten arbeiten. C speichert ganze Zahlen in Zweierkomplement, jedoch mit einer festen Anzahl von Bits. Bitweise Python-Operatoren wirken auf Zweierkomplementwerte, aber als hätten sie eine unendliche Anzahl von Bits: Bei positiven Zahlen erstrecken sie sich mit Nullen nach links bis unendlich, negative Zahlen mit Einsen nach links. Der
&
Operator ändert diese linke Einsenfolge in Nullen und lässt Ihnen nur die Bits übrig, die in den C-Wert passen würden.Das Anzeigen der Werte in hexadezimaler Darstellung kann dies klarer machen (und ich habe die Zeichenfolge von f als Ausdruck umgeschrieben, um zu zeigen, dass wir an 32 oder 64 Bit interessiert sind):
>>> hex(i) '-0x690c18' >>> hex (i & ((1 << 32) - 1)) '0xff96f3e8' >>> hex (i & ((1 << 64) - 1) '0xffffffffff96f3e8L'
Bei einem 32-Bit-Wert in C steigen positive Zahlen auf 2147483647 (0x7fffffff), und bei negativen Zahlen wird das oberste Bit von -1 (0xffffffff) auf -2147483648 (0x80000000) gesetzt. Für Werte, die vollständig in die Maske passen, können wir den Prozess in Python umkehren, indem wir eine kleinere Maske verwenden, um das Vorzeichenbit zu entfernen und dann das Vorzeichenbit zu subtrahieren:
>>> u = i & ((1 << 32) - 1) >>> (u & ((1 << 31) - 1)) - (u & (1 << 31)) -6884376
Oder für die 64-Bit-Version:
>>> u = 18446744073702667240 >>> (u & ((1 << 63) - 1)) - (u & (1 << 63)) -6884376
Dieser inverse Prozess lässt den Wert unverändert, wenn das Vorzeichenbit 0 ist, aber offensichtlich ist es keine echte Inverse, denn wenn Sie mit einem Wert begonnen haben, der nicht in die Maskengröße passt, sind diese Bits weg.
quelle
Python hat keine vorzeichenlosen Typen eingebaut. Sie können mathematische Operationen verwenden, um ein neues int zu berechnen, das den Wert darstellt, den Sie in C erhalten würden, aber es gibt keinen "vorzeichenlosen Wert" eines Python-int. Das Python-Int ist eine Abstraktion eines ganzzahligen Werts, kein direkter Zugriff auf eine Ganzzahl mit fester Byte-Größe.
quelle
Sie können die in
struct
Python integrierte Bibliothek verwenden:Kodieren:
import struct i = -6884376 print('{0:b}'.format(i)) packed = struct.pack('>l', i) # Packing a long number. unpacked = struct.unpack('>L', packed)[0] # Unpacking a packed long number to unsigned long print(unpacked) print('{0:b}'.format(unpacked))
Aus:
-11010010000110000011000 4288082920 11111111100101101111001111101000
Dekodieren:
dec_pack = struct.pack('>L', unpacked) # Packing an unsigned long number. dec_unpack = struct.unpack('>l', dec_pack)[0] # Unpacking a packed unsigned long number to long (revert action). print(dec_unpack)
Aus:
-6884376
[ HINWEIS ]:
>
ist BigEndian Operation.l
ist lang.L
ist lange nicht signiert.amd64
Architekturint
undlong
sind 32 - Bit, also Sie nutzen könnteni
undI
stattl
undL
sind.quelle
Verwenden Sie einfach abs, um unsignierte in signierte in Python zu konvertieren
a=-12 b=abs(a) print(b)
Ausgabe: 12
quelle
abs()
Gibt den absoluten Wert einer Zahl zurück. Das Argument kann eine einfache oder lange Ganzzahl oder eine Gleitkommazahl sein. Wenn das Argument eine komplexe Zahl ist, wird seine Größe zurückgegeben. Dies gibt per Definition nicht immer eineunsigned
Variable zurückPython verfügt nicht über eine integrierte Funktion zum Konvertieren von int in unsigned int. Stattdessen hat es eine lange Reichweite.
>>> val = 9223372036854775807 (maximum value of int 64) >>> type(val) <type 'int'> >>> val += 1 >>> type(val) <type 'long'>
Durch Erhöhen des Werts von val um 1 überschreite ich die Grenze einer vorzeichenbehafteten 64-Bit-Ganzzahl und der Wert wird in eine lange konvertiert. Wenn Python eine vorzeichenlose Ganzzahl verwendet oder konvertiert hätte, wäre val immer noch ein int gewesen. Oder nicht lange.
Vorzeichenbehaftete Ganzzahlen werden durch ein Bit dargestellt, normalerweise das höchstwertige Bit, das für positive Zahlen auf 0 oder für negative Zahlen auf 1 gesetzt wird. Was val & 0xff tut, ist tatsächlich val & 0x000000ff (auf einem 32-Bit-Computer). Mit anderen Worten wird das vorzeichenbehaftete Bit auf 0 gesetzt und ein vorzeichenloser Wert emuliert.
Ein Beispiel:
>>> val = -1 >>> val & 0xff 255
quelle
Seit Version 3.2:
def toSigned(n, byte_count): return int.from_bytes(n.to_bytes(byte_count, 'little'), 'little', signed=True)
Ausgabe :
In [8]: toSigned(5, 1) Out[8]: 5 In [9]: toSigned(0xff, 1) Out[9]: -1
quelle