(Für mich) unverständliches Ergebnis bei binärem Operator ~
-
signed int a=0; cout<<(~a>>1); //ausgabe: -1
Warum das? Wenn ich das richtig verstehe, ist null binär doch:
00000000000000000000000000000000
Wenn ich das invertiere müsste es doch sein:
11111111111111111111111111111111
Wenn ich das nu verschiebe, um das Vorzeichen los zu werden, müsste es doch so aussehen, oder?
01111111111111111111111111111111
Also eine große Zahl???
-
Hallo,
laut Draft und bestimmt auch laut Standard, ist das Ergebnis compilerspezifisch, wenn der linke Operant ein Negatives Ergebnis beinhaltet (was hier ja der Fall
ist).Um das erste Bit dennoch zu loeschen, kannst du das so machen:
i &= (1<<30);
mfg
v R
-
hängt vom Typ von a ab (signed / unsigned)
Es gibt zwei verschiedene Shift-Operationen:
Arithmetic: vorzeichen bleibt erhalten, bei shift right wird das vorzeichen bit eingeschoben
Logic: alle Bits werden verschoben, bei shift right wird 0 eingeschobenC/C++ unterscheidet das am Vorzeichen des werts: signed - werte werden arithmetisch, unsigned-typen logisch geschoben.
-
Natuerlich kann nur ein sigend-Typ ein negatives Ergebnis beinhalten
mfg
v R
-
Und warum ist dann
~a*-1
1?
Jetzt müsste doch die größtmögliche nicht vorzeichenbehafte Zahl rauskommen?
Und warum bitte ist~a
auch -1???
(Ich hab Visual Studio .NET 7.1 Enterprise Architect)
-
ness schrieb:
Und warum ist dann
~a*-1
1?
Jetzt müsste doch die größtmögliche nicht vorzeichenbehafte Zahl rauskommen?Was kommt bei -1 * -1 raus?
Und warum bitte ist
~a
auch -1???
(Ich hab Visual Studio .NET 7.1 Enterprise Architect)Weil a vorher 0 war und jetzt hast du das Bitkomplement gebildet. Alle Bits werden
auf 1 gesetzt. Da es sich hier um einen sigend-Typ handelt, wird das vordere
Bit als das Vorzeichenbit behandelt. Das ist jetzt 1 und das steht fuer -. Daher
-1.mfg
v R
-
1. ist mir klar, ich dacht das liegt an dem Schiebeoperator...
2. Aber warum ist das "Bitkomplement" von 0 1? (Oder heißt Bitkomplement etwa net alle einsen zu nullen und alle nullen zu einsen?)
Und wenn, wie du sagst, alle bits auf 1 Gesetzt werden, müsste die Zahl doch deutlich größer(kleihner, da vorzeichenbehaftet) als eins sein? (2 hoch 31???)
-
ness schrieb:
1. ist mir klar, ich dacht das liegt an dem Schiebeoperator...
2. Aber warum ist das "Bitkomplement" von 0 1? (Oder heißt Bitkomplement etwa net alle einsen zu nullen und alle nullen zu einsen?)
Und wenn, wie du sagst, alle bits auf 1 Gesetzt werden, müsste die Zahl doch deutlich größer(kleihner, da vorzeichenbehaftet) als eins sein? (2 hoch 31???)Bitkomplement bedeutet aus 0 wird 1 und aus 1 wird 0, sprich die Bits werden
invertiert. Wenn a = 0 ist, dann sieht dein Bitmuster so aus:0000 0000 0000 0000 0000 0000 0000 0000
nun ~a
1111 1111 1111 1111 1111 1111 1111 1111
und das ist -1.
1111 1111 1111 1111 1111 1111 1111 1110
ist -2 und
1111 1111 1111 1111 1111 1111 1111 1101
ist -3 usw. Das kannst du ganz leicht ausprobieren:
int main() { int i = 0; i = ~i; cout<<i<<endl; i &= ~(1<<0); //bitmuster: 1111 1111 1111 1111 1111 1111 1111 1110 cout<<i<<endl; i &= ~(1<<1); //bitmuster: 1111 1111 1111 1111 1111 1111 1111 1100 cout<<i<<endl; return 0; }
mfg
v R
-
Warum das? Ham wir net alle in der Schule gelernt, das:
000 = 0 001 = 1 010 = 2 011 = 3 100 = 4 101 = 5 111 = 6
?
-
Das haben wir bei positiven Zahlen gelernt, aber nicht bei negativen
mfg
v R
-
Hi,
ness:
diese Schreibweise bezieht sich wie gesagt nur auf unsignierte Datentypen. Diese zeichnen sich dadurch aus, dass das 1. Bit ein ganz normales Bit für die Zahl ist.
Bei signierten Datentypen bedeutet das erste Bit aber wie gesagt das Vorzeichen.
Allerdings ist:10 nicht -0, sondern -1. Da -0 = +0 hat man durch die invertierte Schreibweise des Restes (also alles bis auf das Vorzeichenbit) mehr Zahlenmöglichkeiten.
MfG Eisflamme
-
Für die binärkodierung negativer Zahlen gibnt es zwei gängige Verfahren:
Einerkopmplement: -a ≡ ~a
Zweierkomplement: -a ≡ ~a+1
Bei beiden gibt das höchstwertige Bit das Vorzeichen an.Beide haben den Vorteil, daß bei arithmetischen Operationen nicht zwischen Vorzeichenlos und Vorzeichenbehalftet unterschieden wird. Im einerkomplement gibt es aber zwei Darstellungen für 0, was Vergleiche relativ kompliziert macht
Der C++ - Standard macht keine Garantien zur binären Darstellung negativer Zahlen.
-
letzlich wird jeder compiler die standard datentypen so codieren, wie der prozessor sie normalerweise verwendet - also für x86 prozessoren immer die zweierkomplementdarstellung.
-
...genau deswegen macht der Standard ja auch keine Vorschriften.
-
virtuell Realisticer schrieb:
Das haben wir bei positiven Zahlen gelernt, aber nicht bei negativen
mfg
v RJa, aber wenn ich mit -1 multipliziere ist die Zahl doch wieder positiv? Ach nein, das hängt sicher davon ab, ob die zahl negativ sein kann...
Dann frag ich mal in die Runde: Wie kann ich mittels den binären Operatoren die Obergrenze eines vorzeichen-behafteten types ausgeben? Und wo genau ist das "Vorzeichen-bit"? Ganz "links" oder ganz "rechts"? (Auf einer x68-Architektur)
-
Es ist das höchstwertige Bit, üblicherweise ganz links dargestellt (aber das ist nur Konvention. Ich fände Spiralmuster zwar hübscher, aber die sind halt nicht so praktisch)
Da du eigentlich überhaupt nichts über die Darstellung weißt, wird es schwierig. Vielleicht
int i=0; while(i+1>0) ++i;
. aber das dauert etwas.
Wenn du die Kodierung kennst, geht alles natürlich ein bißchen schneller.
-
Ja, sowas hab ich auch schon, aber haste das schinmal mit long long probiert?
Woher könnte ich denn Informationen über die Darstellung beziehen? Prinzipiell müsste das Ergebnis binär gesehen ja ziemlich regelmäßig sein, bei unsigned eben 111111111111...
-
Ja, aber wenn ich mit -1 multipliziere ist die Zahl doch wieder positiv? Ach nein, das hängt sicher davon ab, ob die zahl negativ sein kann...
Du hattest a = 0. ~a ist dann -1 und das *-1 ist 1. Was ist daran ungewoehnlich?
Ja, sowas hab ich auch schon, aber haste das schinmal mit long long probiert?
Woher könnte ich denn Informationen über die Darstellung beziehen? Prinzipiell müsste das Ergebnis binär gesehen ja ziemlich regelmäßig sein, bei unsigned eben 111111111111...Wieso sollte es regelmaessig sein? In diesem Falle wuerde es eine +0 und eine -0
geben. Und genau damit das nicht passiert, sind 32 einser-Bits -1 und nicht die
kleinste negativ darstellbare Zahl. Damit du diese Zahl bekommst, kannst du das
vorderste Bit auf 1 setzen:int a = 0; a = (1<<31);
mfg
v R
-
OK, und woher bekomme ich ne positive Zahl? Und warum ist long long a=(1<<63) 0?
-
Weil long long auf deinem compiler auch keine 4 bit hat?
-
long long == __int64 == 64bit? So stehts in der msdn?