Bitmuster darstellen (auf Bits zugreifen). Bitte um Anregungen.

spiderflo

Mitglied
Hallo alle zusammen.
Ein erfolgreiches neues Jahr mal allen!

Also..
ich habe ein Projekt bei dem es darum geht die Gleitkommaarithmetik beim Microsoft und Borland Compiler herauszufinden und zu vergleichen.
Ergebnis sollte darstellen wie
- Exponent,
- Mantisse,
- VZ-Mantissen,
- Charakteristik,
- EingespartesMantissenBit (die 1. Eins bei den Mantissen) aufgeteilt sind.
Bei Float, Double und Long Double (nur Borland, oder?) in C.

Mir wurde folgendes gesagt: (EMB = Einges.Man.Bit. = kommt gar nicht vor. wird vorausgesetzt)
VZm | Expos | EMB | Mantissen
1 (-) | 10001010 | (1) | 11010000000011110000010

das würde - 0, (1)11010000000011110000010 *2 ^12+126 = - 3712,4693 im 10Sys
also normalisierte Darstellung mal der Basis hoch (Exponenten+Charakteristik)
Das ist jetzt ein Beispiel für C-Float gewesen.
Hier noch eines mit einer etwas einfacheren Zahl, nähmlich 5:
VZm | Expos | EMB | Mantissen
0 (+) | 10000001 | (1) | 01000000000000000000000

das würde - 0, (1)01 *2 ^3+126 und das wäre jetzt 5 in unserem 10er System
Ich habe das obrige Beispiel trotzdem angegeben weil Float ja 4 Byte hat,
das bedeutet das die obere Zahl so dargestellt werden müsste:
. Byte 1 | Byte 2 | Byte 3 | Byte 4
11000101 | 01101000 | 00000111 | 10000010
stimmt aber nicht, sondern so:
. Byte 4 | Byte 3 | Byte 2 | Byte 1
10000010 | 00000111 | 01101000 | 11000101
Ich hoffe ich habe hier jetzt keinen Blödsinn geschrieben.
Mein Problem ist. Ich habe keine Ahnung wie ich Zugang zu den einzelnen Bits habe !?
Wie komme ich wenn ich Float = 5.0 definiere an das Bitmuster 01000000110100... ?

Ich hoffe Ihr habt das jetzt hier verstanden was ich geschrieben habe, beziehungsweise Ihr wisst es schon und könnt mir eine Anregung geben. Ich arbeite vorwiegend in MVC++6.

Schönen Nachmittag noch und
schon jetzt Vielen Dank
Florian Bräuer
 
Er hat mir leider die Blanks aus der Darstellung rausgelöscht.
Also Sry der Unübersichtlichkeit. Hoff Ihr findet euch trotzdem gut zurecht. Danke!
 
Der gute alte c-cast macht's möglich:

unsigned long dwU32 = *(unsigned long*)&floatWert;

Das Umgewurste über Pointer ist notwendig, da sonst die implizite float-nach-int-Funktion (ftol) eingesetzt wird.

Bei dwU32 kannst du jetzt mit den Bit-Operatoren die einzelnen Bits prüfen.
 
Es ist jetzt ein Problem aufgetaucht:
Ich will jetzt nicht nur einen Floatwert im Bitmuster darstellen,
sondern auch einen Doublewert.

Unsigned Long Int zeigt auf 4 Byte
Float ebenfalls -> kein Problem
und wie jetzt bei Double? 8 Bytes ...

Meine erste Idee war einfach splitten.
Wie sage ich:
unsigned long int vierbyte = *(unsigned long int*) (&c_double + DIEGROSZEVONLONG)
Mit sowas habe ich mich noch nicht beschäftigt.
Danke schon jetzt
Florian
 
Entweder so wie in der PM oder so:

unsigned long int vierbyte = *( ( (unsigned long int*) &c_double ) + 1 );

Die Klammer um den Cast ist wichtig, damit der Pointer vom Typ unsigned long wird. Dann einen draufzählen (der Pointer springt ja dann automatisch um die Grösse eines unsigned long weiter).
Achtung: Der Code geht natürlich davon aus, dass ein double die Grösse von 2 unsigned long hat.
 
Achtung: Der Code geht natürlich davon aus, dass ein double die Grösse von 2 unsigned long hat.

Das wiederspricht sich dann aber damit, dass man das auch bei LongDouble anwendet,
da dieser ja dann 2,5 unsigned Longs groß ist, oder.
Oder kann der 3te dann einfach nur auf 2 Byte zeigen, bzw. eh mehr aber ich verwende nur 2 Byte? Würde das gehen. Sry das ichs nicht einfach probier. Aber das geht grad nicht.
Danke und einen schönen Samstag noch
Florian
 

Habt ihr eine schnelle Antwort, wenn ich behaupte,
dass er mir bei
Code:
unsigned long int vierbyte = *( ( (unsigned long int*) &c_double ) + 1 );
das erste Bit stielt?

weiß nicht ob der Code zu verwirrend ist, nur trotzdem als Hilfestellung:
Code:
 unsigned long int pot2 (short int exponent) {
 	 short int i	= exponent;
 	 unsigned long int ret = 0; // Start mit 2^0
 	 if (exponent>0) ret = 1; // Steht für 2^1
 	 for (i = i; i>=2; i--) ret *= 2; // Weiter rechnen bis 2^2
 	 return ret;
 }
Code:
 printf ("Speicherung:\n\n\t Byte 8 Byte 7 Byte 6 Byte 5 Byte 4 Byte 3 Byte 2 Byte 1\n\t "); textcolor (8);
 double c_double = 5.0;
 unsigned long int vierbytes = *(unsigned long int*) &c_double;
 short int i, x, y; // i = Bitindex | x = Summand zum Bitindex | y = 1Byteindex
 for (i = 8, x = 1, y = 1; y<=9 ; i--) { // Bytemuster ausgeben
 	 printf ("%i", ((vierbytes & pot2 (i)) == pot2 (i)) ? true : false); // Einzelne Bits ausgeben
 	 if (i==1 || i==1+8 || i==1+16 || i==1+24) printf (" "); // Trennabstände
 	 if (i==x) x += 8, i = x+8, y++; // Einzelne Bytes umschalten
 	 if (y==5) {
 		 i = 8, x = 1, y++; // Nächste 4er Byte-Kette
 		 vierbytes = *(((unsigned long*) &c_double ) + 1);
 	 }
 }
ich kann dieses Abstandlöschen dieses Forums nicht leiden ;)
 
Zuletzt bearbeitet:
Dein Code ist nicht im eigendlichen Sinne verwirrend. Er ist nur viel zu kompliziert um eine im Grunde einfache Aufgabe zu lösen. Versuchs mal mit folgendm Code.

Code:
                // davon ausgehend das char = 1 byte ist, für das Beispiel reicht mir die Annahme...
	char* ptr = (char*) &c_double; 

	// 8 Bytes ausgeben
	for( int i=0; i<8; ++i) {
		// 8 Bit pro Byte ausgeben, von links nach rechts
		for( int j=7; j>=0; --j) {
			printf( "%i", (*ptr & (1<<j)) ? 1 : 0 );
		}
		ptr++;
		sprintf(" ");
	}

Ach ja, der Code klaut keine Stellen ;) Um es genau zu nehmen müsste man noch mit sizeof(char) prüfen ob char 1 oder 2 Byte groß ist und dann die Schleifen entsprechend anpassen.
 
Zurück