2009-07-24 14 views
5

Dies ist ein Zweifel in Bezug auf die Darstellung von Bits vorzeichenbehafteter Ganzzahlen. Wenn Sie beispielsweise -1 darstellen möchten, entspricht dies dem Zweierkomplement von (+1). Also wird -1 als 0xFFFFFFF dargestellt. Jetzt, wenn ich meine Zahl um 31 verschiebe und das Ergebnis drucke, kommt es als -1 zurück.Bits Repräsentation von negativen Zahlen

signed int a = -1; 
printf(("The number is %d ",(a>>31));//this prints as -1 

Also kann mir bitte jemand erklären, wie die Bits für negative Zahlen dargestellt werden?

Danke.

+0

Betrachten wir es aus einem anderen Blickwinkel: man denke an irgendeine N-Bit (Vorzeichen verlängernde) Rechtsverschiebung als Division durch 2^N, Abrunden nach UNTEN (gegen minus unendlich, nicht gegen 0.) Also -1 nach rechts verschoben (mit Vorzeichen) Verlängerung) wird immer -1 produzieren. – vladr

Antwort

10

Wenn das obere Bit Null ist, ist die Zahl positiv. Wenn es 1 ist, ist die Anzahl negativ.

Negative Zahlen, die nach rechts verschoben sind, verschieben eine "1" als das oberste Bit, um die Zahl negativ zu halten. Deshalb bekommst du diese Antwort.

Weitere Informationen zum Zweierkomplement finden Sie unter this Stackoverflow question.


@Stobor weist darauf hin, dass einige C-Implementierungen 0 in den High-Bit statt 1 verschieben könnten [in Wikipedia bestätigt.] In Java ist es zuverlässig eine arithmetische Verschiebung.

Aber die vom Fragesteller ausgegebene Ausgabe zeigt, dass sein Compiler eine arithmetische Verschiebung ausführt.

+0

Aber shud es Druck als -1, sollte es als 1 Ritus seit den obersten, aber ist 1, die eine negative Zahl darstellt drucken. –

+1

@Nosredna: Sie sollten auch erwähnen, dass das Verhalten des Füll-mit-Zeichen-Bits implementierungsspezifisch ist. – Stobor

+0

Da es eine negative Zahl darstellt, warum sollte es eine positive Zahl drucken? – Nosredna

1

Dies ist eine arithmetische Schiebeoperation, die das Vorzeichenbit beibehält und den Mantissenteil einer vorzeichenbehafteten Zahl verschiebt.

prost

8

Der Standard C läßt es undefiniert, ob die Rechtsverschiebung eines negativen (notwendigerweise signierten) integer verschiebt Nullen (logische Verschiebung nach rechts) oder Vorzeichenbits (arithmetische Verschiebung nach rechts) in der höchstwertigen Bits. Es liegt an der Implementierung zu wählen.

Folglich stellt portabler Code sicher, dass es keine richtigen Verschiebungen bei negativen Zahlen durchführt. Entweder wandelt es den Wert vor dem Verschieben in den entsprechenden vorzeichenlosen Wert um (wobei garantiert wird, dass eine logische Verschiebung nach rechts verwendet wird, indem Nullen in die freigewordenen Bits gesetzt werden), oder es stellt sicher, dass der Wert positiv ist, oder toleriert die Abweichung in der Ausgabe.

+0

Oder es könnte "oder" in der oberen Bit (oder Bits) nach der Verschiebung. – Nosredna

+0

Vielen Dank für alle Antworten.Gut ich bin noch nicht mein doyubt noch gelöscht.So ist es Compiler oder Hardware-spezifisch ??? –

+2

@Maddy: Es hängt von der Hardware und dem Compiler ab.Wenn beispielsweise eine bestimmte CPU nur ein logisches Verschiebungsrecht (LSR) und kein arithmetisches Verschiebungsrecht (ASR) aufweist, dann verwenden die Compiler für diese Maschine den LSR und nicht den nicht existierenden ASR. Es hängt auch vom Compiler ab; Selbst wenn eine Maschine sowohl ASR als auch LSR hat, könnte sich ein Compiler-Schreiber aus irgendwelchen Gründen dafür entscheiden, LSR sowohl für vorzeichenbehaftete als auch vorzeichenlose Mengen zu verwenden. Es könnte schneller sein; es könnte mit anderen Plattformen konsistent sein, auf denen derselbe Compiler auch läuft; Es könnte sein, dass die Person, die den Compiler schreibt, ASR nicht mag. –

1

Grundsätzlich gibt es zwei Arten von Rechtsverschiebung. Eine vorzeichenlose Rechtsverschiebung und eine rechtsseitige Verschiebung. Eine vorzeichenlose Verschiebung nach rechts verschiebt die Bits nach rechts, wodurch das niedrigstwertige Bit verloren geht und das höchstwertige Bit durch eine 0 ersetzt wird. Bei einer vorzeichenbehafteten Rechtsverschiebung werden die Bits nach rechts verschoben, was am wenigsten bewirkt bedeutsames Bit ist verloren, und das bedeutendste Bit, um bewahrt zu werden. Eine vorzeichenbehaftete Verschiebung nach rechts teilt die Zahl durch eine Zweierpotenz (entsprechend der Anzahl der verschobenen Stellen), während eine vorzeichenlose Verschiebung eine logische Verschiebeoperation ist. Der Operator ">>" führt eine vorzeichenlose Verschiebung nach rechts aus, wenn der Datentyp, auf dem er ausgeführt wird, vorzeichenlos ist, und führt eine signierte Rechtsverschiebung durch, wenn der Datentyp, auf dem er ausgeführt wird, signiert ist. Was Sie also tun müssen, ist das Objekt auf einen vorzeichenlosen Integer-Typ zu transformieren, bevor Sie die Bit-Manipulation durchführen, um das gewünschte Ergebnis zu erhalten.

+0

Nicht unbedingt eine "signed shift" für vorzeichenbehaftete Ganzzahlen (obwohl es sehr häufig so gemacht wird) - es hängt vom Compiler und/oder der Hardware ab. –

+0

Ja. Stimmt. Ich habe so lange auf gut benommenen Laptop-/Desktop-/Server-Maschinen programmiert, die eine Variante von x86 ausführen und mit GCC kompilieren, dass es oft leicht ist, den Unterschied zwischen den Annahmen, die für die aktuelle Anwendung angemessen sind, und dem Standard zu vergessen Garantien. –

0

EDIT: Wenn die unten geschrieben wurde, wurde der Code in der Frage geschrieben, wie:

unsigned int a = -1; 
printf(("The number is %d ",(a>>31));//this prints as -1 

Wenn unsigned int mindestens 32 Bit breit ist, dann wird Ihr Compiler nicht wirklich zu produzieren erlaubt ist -1 als Ausgabe von diesem (mit der kleinen Einschränkung, dass Sie den vorzeichenlosen Wert zu int werfen sollten, bevor Sie es an printf übergeben).

Da a ein vorzeichenloses int ist, muss -1 dem Wert von UINT_MAX zugewiesen werden (als kleinster nicht negativer Wert kongruent zu -1 modulo UINT_MAX + 1). Solange unsigned int mindestens 32 Bits auf Ihrer Plattform hat, wird das Ergebnis der Verschiebung dieser vorzeichenlosen Menge um 31 UINT_MAX dividiert durch 2^31, was in int passen muss. (Wenn nicht signiertes int 31 Bits oder kürzer ist, kann es erzeugen, was es mag, weil das Ergebnis der Verschiebung nicht spezifiziert ist).

Verwandte Themen