(Für mich) unverständliches Ergebnis bei binärem Operator ~



  • 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 eingeschoben

    C/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.


  • Mod

    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 R

    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...
    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?


  • Mod

    ich tip mal darauf,d ass der ausdruck (1<<63) zunächst als long ausgewertet und dann nach long long gecastet wird. wenn das so ist, müsste

    long long a = (long long)1 << 63;
    

    eigentlich funktionieren.


Anmelden zum Antworten