Seite 1 von 1

C++ und der Shift-Operator

Verfasst: So Okt 14, 2012 10:17 am
von Leverator
Moin zusammen,

ich habe hier ein Problem, das mir Kopfzerbrechen bereitet.
Aber zunächst mal der Code:

Code: Alles auswählen

#include <iostream>
#include <stdint.h>

int main( int argc, char *argv[] ) {

        int64_t x;
        int64_t y;
        int64_t _M = 24;

        x = 1024 << _M;
        y = 2048 << _M;

        std::cout << "x = " << x << std::endl;
        std::cout << "y = " << y << std::endl;

        std::cout << "x*y = " << x*y << std::endl;
        std::cout << ( (x*y)>>_M ) << std::endl;


        return 0;
}                     
Startet man nach dem Kompilieren dieses Beispiel, erscheint folgende Ausgabe:

Code: Alles auswählen

/tmp$ ./test 
x = 0
y = 0
x*y = 0
0

Und nun die goldene Frage: WARUM?
Für x erwarte ich den Wert 17179869184. Y muss entsprechend doppelt so hoch sein.

Hintergrund dieses Beispiels ist eine Berechnung von Fliesskommawerten mit Hilfe von ganzzahligen Ints. Darum verwende ich int64_t um genügend Platz für die Nachkommastellen zu haben.
Ich möchte also einfach eine Operation wie a*b durchführen. Ich definiere den Punkt an dem das Komma gesetzt werden soll mit _M. Hier also das 24. Bit.

Wer mag mir da weiterhelfen?

Vielen Dank,
Lev

Re: C++ und der Shift-Operator

Verfasst: So Okt 14, 2012 10:46 am
von Kerli
Leverator hat geschrieben:

Code: Alles auswählen

x = 1024 << _M;
y = 2048 << _M;
Hier musst du aufpassen. Konstanten sind ohne nähere Typangaben entweder int oder double. Wenn du also wie in diesem Fall einen größeren Datentyp möchtest musst du entweder L (long), LL (long long) oder UL/ULL (unsigned long (long)) and die Konstante anhängen. (zb. 1024L)

Re: C++ und der Shift-Operator

Verfasst: So Okt 14, 2012 11:08 am
von Leverator
Hallo Kerli,

danke für diesen Hinweis.

Da meine Daten eigentlich als int32_t-Array vorliegen, habe ich den o.g. Code wie folgt geändert:

Code: Alles auswählen

x = static_cast<int64_t>(1024) << _M;
y = static_cast<int64_t>(2048) << _M;
Die Ausgabe sieht schon besser aus, jedoch immernoch nicht so wie ich es mir vorstelle:

Code: Alles auswählen

/tmp$ ./test 
x = 17179869184
y = 34359738368
x*y = 0
0
Hast Du noch weitere Hinweise,

Grüße,
Lev

Re: C++ und der Shift-Operator

Verfasst: So Okt 14, 2012 11:31 am
von Xin
Kerli hat geschrieben:
Leverator hat geschrieben:

Code: Alles auswählen

x = 1024 << _M;
y = 2048 << _M;
Hier musst du aufpassen. Konstanten sind ohne nähere Typangaben entweder int oder double.
Solange sie keinen Punkt enthalten sind sie int, haben sie einen Punkt, so sind sie double.

Ein int mit dem Wert 1024 << 24 ergibt 0, da Du einen 32 Bit int hast, wo Du eine Zahl mit 10 Bit um 24 Bits verschiebst. Das signifikante Bit 10, was 1024 repräsentiert, fliegt damit raus. Übrig bleiben 32 Nullen.

Wenn Du zwei 64 Bit Zahlen, die auf den Bits 0-31 nur '0'en haben (das ist bei 1024<<24 und 2024<<24 der Fall), multiplizierst, kommen 64 '0'en raus. Eine 64Bit-Zahl, die nur Nullen enthält ist... 0.
Alles was drüber liegt, wird abgeschnitten. Integer sind eben keine Fließkommazahlen.

Deine Multiplikation benötigt also entweder 128Bit-Integers oder Fließkommazahlen mit dem Risiko, dass die Multiplikationen nicht mehr exakt sind.

Re: C++ und der Shift-Operator

Verfasst: Mi Okt 17, 2012 1:22 pm
von oenone
Leverator hat geschrieben:Die Ausgabe sieht schon besser aus, jedoch immernoch nicht so wie ich es mir vorstelle:
Was stellst du dir denn vor?