casten....



  • toolen schrieb:

    Mit: log(a)/log(e) erhalte ich das gewünschte Ergebnis (in der Theorie!).

    Wie kommst du darauf? log(e) ist 1.

    Den Logarithmus zur Basis 2 ermittelst du, indem du den natürlichen Logarithmus durch den natürlichen Logarithmus von 2 teilst:

    double log2a = log(a) / log(2);
    

    Nachtrag. Bei:

    e = (int) log(abs(a))/log(2)
    

    wandelst du nur den Teil log(abs(a)) nach int um, nicht das Ergebnis der Division.



  • puh, ok. Nochmal ein Fehler.

    aber nur in der Erklärung. Im code (z.B. Zeile 7, Exponent-Teil) ist es richtig:

    log(abs(a))/log(2)

    Gruß



  • Bingo!

    dat war et! Vielen Dank!



  • Tja zu früh gefreut...

    #include <stdio.h>
    #include <math.h>
    
    #define NEIN 0
    #define JA 1
    
    void darst_bin(unsigned int zahl);
    
    int main()
    {
    	int debug=JA;
    	float a;
    	a = 11.25;
    	unsigned long m;            // Mantisse
    	unsigned long e;		// Exponent
    	unsigned long s;		// Sign
    	int feld[16];
    	printf("**********************************\n\n");
    	printf("* Umzuwandelnde Zahl = %f    \n\n", a);
    	printf("**********************************\n");
    // *** Vorzeichen - Flag ***
    
    	if (a<0)
    		s = 1;
    	else
    		s = 0;
    	if(debug)
    		printf("**DEBUG**:\n   Sign-Flag = %u\n", s);
    
    // *** Exponent ************
    
    	e = 127 + (int) (log(abs(a))/log(2));
    
    	if(debug)
    		printf("**DEBUG**:\n   Exponent = %u\n", e);
    		darst_bin(e);
    
    // *** Mantisse ************
    
    	printf("Mantisse = %u\n", (unsigned int) (((abs(a)/pow(2,e-127))-1)*pow(2,23)));
    	m = (unsigned int) (((abs(a)/pow(2,e-127))-1)*pow(2,23));
    
    	if(debug)
    		printf("**DEBUG**:\n   Mantisse = %u\n", m);
    		darst_bin(m);
    
    	return 0;
    
    }
    
    void darst_bin(unsigned int zahl)
    {
    	int count;
    	printf("%u (10) = ", zahl);
    	for (count=23; count >= 0; count--)
    	{
    		if (zahl / (int) pow(2,count))
    		{
    			zahl = zahl % (int) pow(2,count);
    			printf("1");
    		}
    		else
    			printf("0");
    	}
    	printf(" (2)\n");
    }
    

    Das Problem ist jetzt, daß zum Beispiel bei der Umwandlung von 11,25 (wie im Quellcode angegeben), die Mantisse mit 3145728 berechnet wird. Tatsächlich ist laut
    [url]
    http://de.wikipedia.org/wiki/Gleitkommazahl#Berechnung_einer_IEEE_single_Gleitkommazahl_.2832-Bit-Gleitkommazahl.29
    [/url]
    die Mantisse 3407872. Mein Taschenrechner meint das gleiche. Es muss also an dem Quellcode hier liegen. Um zu verhindern, daß die Zahlen abgeschnitten werden, habe ich die Mantisse als unsigned long deklariert.

    Ich würde mich freuen, wenn mir jemand helfen könnte.

    Viele Grüße, toolen

    P.S: die Formeldn für die Berechnung der Mantisse und dem Exponenten habe ich ebenfalls von o.g. Link



  • In C gibt abs immer int zurück. Nimm fabs.



  • toolen schrieb:

    Ich möchte ein Programm schreiben, daß eine float-Zahl in Vorzeichen, Mantisse und Exponent aufdröselt. Beim Berechnen des Exponenten habe ich ein Problem:

    Also wenn es dir nur um das "Aufdröseln" geht, warum berechnest du die Werte überhaupt? Du kannst sie ja aus dem Float direkt rausziehen. Das wäre schneller und einfacher.



  • Hallo,

    @TactX: Angenommen, ich habe eine Variable a:

    float a = -11,75;
    

    Wie erhalte ich dann das 1., 2., 3.,.... Bit?
    Ein float - Pointer auf die Variable kann es ja nicht sein, oder?

    Gruß, toolen



  • Ausnahmsweise mal fertiger Code:

    #include <stdio.h> 
    
    int main(void){
            unsigned int *fakefloat;
            float zahl;
            unsigned int mant;        // Mantisse
            unsigned int expo;        // Exponent
            unsigned int sign;        // Sign
    
            zahl=11.25;
    
            // Wir nehmen an, dass sizeof(unsigned int)==sizeof(float)
            fakefloat=&zahl;          // Spuckt natuerlich eine Warnung aus  
    
            // Ueber Bitshifts und Bitmasken ziehen wir die einzelnen Komponenten raus
            sign = *fakefloat >> 31;
            expo = *fakefloat >> 23 & 0x7FFFFFFF;
            mant = *fakefloat & 0x7FFFFF;
    
            printf("Sign = %u\nExpo = %u\nMant = %u\n", sign, expo, mant);
    
            return 0;
    }
    


  • Herzlichen Dank für die Antwort,

    eine Frage noch, die mich etwas verunsichert:

    würde es nicht reichen, anstatt:

    expo = *fakefloat >> 23 & 0x7FFFFFFF;
    

    folgendes zu schreiben:

    expo = *fakefloat >> 23 & 0xFF;
    

    Der Exponent wird ja nur mit 8 Bit dargestellt.

    Kann man den gcc anweisen, Warnungen nicht anzuzeigen?

    Gruß und nochmal Danke!



  • Jo, du hast vollkommen recht. 0x7FFFFFFF ist falsch (bring bei negativem Vorzeichen einen falschen Exponenten).

    Die Warnung kannst du durch einen Cast unterdrücken:

    fakefloat=(unsigned int *)&zahl;
    

    EDIT: 0x7FFFFFFF wäre korrekt, wenn man zuerst die Verundung und dann erst die Shifterei gemacht hätte. Hab das irgendwie verwechselt.


Anmelden zum Antworten