Datentyp Konvertierung (float, int, unsigned int)
-
Hallo,
ich steh grad total auf dem Schlauch. Ich hoffe ihr könnt mir helfen.
Auf meiner Maschine gilt: sizeof(int) = sizeof(unsigned int) = sizeof(float) = 4
Sooo, wenn ich jetzt einen int in eine float Variable schreibe, dann geht das immer (ohne Datenverlust), d.h. INT_MAX passt in float und INT_MIN passt in float.
Erste Frage: WARUM? Wenn ich mir die codierung eines floats anschaue, dann brauche ich doch auch bits für die Nackommastellen...
Wenn ich einen unsigned int in eine float Variable schreibe, dann erhalte ich bei folgendem Samplcode die Ausgabe: 4.29497e+09 4294967295 0float f = UINT_MAX; unsigned int i= (unsigned int)f; std::cout << f << " " << UINT_MAX << " " << i << std::endl;Ich verstehe die 0 in der Ausgabe nicht...

Danke für eure Mühen!
-
Ich bin bei solchen Dingen nicht genug in der Materie drin,
aber ein float hat natürlich Speichertechnisch noch ein paar Besonderheiten.Vielleicht hilft dir dieser Artikel
http://www.mpdvc.de/artikel/FloatingPoint.htm
-
Der Aufbau von Integer und Floats ist gänzlich unterschiedlich, du kannst nicht einfach wild ohne Sinn herumcasten wie es dir gefällt.
Übrigens ist das ein C-Cast, der in C++ nichts zu suchen hat.
-
Trie schrieb:
Auf meiner Maschine gilt: sizeof(int) = sizeof(unsigned int) = sizeof(float) = 4
Sooo, wenn ich jetzt einen int in eine float Variable schreibe, dann geht das immer (ohne Datenverlust), d.h. INT_MAX passt in float und INT_MIN passt in float.
Das mit dem "ohne Datenverlust" stimmt nicht.
Trie schrieb:
Erste Frage: WARUM? Wenn ich mir die codierung eines floats anschaue, dann brauche ich doch auch bits für die Nackommastellen...
Wenn ich einen unsigned int in eine float Variable schreibe, dann erhalte ich bei folgendem Samplcode die Ausgabe: 4.29497e+09 4294967295 0float f = UINT_MAX; unsigned int i= (unsigned int)f; std::cout << f << " " << UINT_MAX << " " << i << std::endl;Ich verstehe die 0 in der Ausgabe nicht...

Du hast undefiniertes Verhalten.
Angenommen, float bedeutet auf Deiner Maschine IEEE 754 32bit float. Angenommen, int ist auch 32Bit breit. Dann ist die Zahl UINT_MAX nicht exakt per float darstellbar. Anscheinend wird in Deinem Fall aufgerundet. f speichert dann also UINT_MAX+1. Diese Zahl ist allerdings nicht per unsigned int darstellbar. Das Konvertieren von Fließkommazahl zu Ganzzahl, wobei der nach eventuellem Abschneiden der Nachkommastellen die verbleibende Zahl nicht im Zieltyp darstellbar ist, ruft undefiniertes Verhalten hervor (böse böse BÖSE!)
Ein 32bit IEEE 754 float besitzt nur 24 signifikante Binärstellen im Falle von normalisierten Zahlen. UINT_MAX wären eigentlich 32 binäre Einsen, also
1,1111111111111111111111111111111 * 2^31Dein
fspeichert anscheinend die Zahl1,00000000000000000000000 * 2^32(aufgerundet). Die Eins vor'm Komma wird nicht explizit abgespeichert. Dann bleiben 23 signifikante Bits, die gespeichert werden. Dazu komme ein Vorzeichenbit und 8 Bits für den Exponenten.
Mach Dich mal schlau, wie das mit den Fließkommazahlen funktioniert. Wikipedia etc etc
kk
-
krümelkacker schrieb:
...ruft undefiniertes Verhalten hervor (böse böse BÖSE!
Das wäre nicht einmal für signed int Typen richtig (implementation defined, aber micht undefined).
Unsigned int Typen haben aber bei Überlauf ein wohl definiertes Verhalten (wrap around mit x modulo 2^(sizeof(T) * CHAR_BIT) ).
unsigned int i = UINT_MAX + 1liefert also definiert 0.
Das Verhalten vom float ist schlimmsten Falls "implementation defined", aber ebenfalls nicht undefiniert.
-
Tachyon schrieb:
krümelkacker schrieb:
...ruft undefiniertes Verhalten hervor (böse böse BÖSE!
Das wäre nicht einmal für signed int Typen richtig (implementation defined, aber micht undefined).
4.9 Floating-integral conversions [conv.fpint]
1 An rvalue of a floating point type can be converted to an rvalue of an integer type. The conversion truncates; that is, the fractional part is discarded. The behavior is undefined if the truncated value cannot be represented in the destination type.ist doch ziemlich undefiniert.
Tachyon schrieb:
Unsigned int Typen haben aber bei Überlauf ein wohl definiertes Verhalten (wrap around mit x modulo 2^(sizeof(T) * CHAR_BIT) ).
Das betrifft nur Arithmetik mit vorzeichenlosen Zahlen (3.9.1/4). Für alles andere gilt das nicht automatisch, deshalb muss es z.B. bei der Konvertierung vorzeichenbehaftet->vorzeichenlos noch einmal extra normiert werden (4.7/2).
Ein Blick in C99 kann helfen
6.3.1.4 Real floating and integer
1 When a finite value of real floating type is converted to an integer type other than _Bool, the fractional part is discarded (i.e., the value is truncated toward zero). If the value of the integral part cannot be represented by the integer type, the behavior is undefined.50)- The remaindering operation performed when a value of integer type is converted to unsigned type need not be performed when a value of real floating type is converted to unsigned type. Thus, the range of portable real floating values is (−1, Utype_MAX+1).
-
camper schrieb:
...
*grummel* Ich hasse den Standard. Aber nun gut...