fließkommer in integer raum (kein cast)



  • Hallo, ich habe folgendes Problem und zwar soll mit Fließkommawerten rein auf Integer ebene gearbeitet werden. Der grund ist der, das am ende das ganze Portiert werden soll auf ein System mit 32bit Int cpu, die keine Fließkommaarithmetik unterstützt. Ich habe mir den IEEE 754 angeschaut und wollte es auch so machen. Nur ist die Frage wie bekomme ich aus einer Fließkommazahl eine Binärdarstellung dieser hin damit ich entsprechend mit Verschiebung die Mantisse den Exponenten und das Vorzeichen holen kann?



  • Sicher, dass es nicht einfacher waere, mit Festkommazahlen zu arbeiten?

    Zurueck zu Deiner Frage: Einfach auf int casten, und dann mit Bitschiebereien in Mantisse und Exponent zerlegen. Oder gleich Mantisse und Exponent in 2 verschiedenen Variablen speichern.



  • Das Problem ist das es möglichst genau sein sollte, weil die Werte Farbwerte wiederspiegeln und die Ergebnisse in den XYZ Raum überführt werden sollen. Aber int tut doch nur runden oder? Und da wären meine Kommastellen ja verschwunden oder hab ich nen denkfehler?



  • Integer-Werte haben keine Nachkommastellen (die werden bei der Umwandlung nichtmal gerundet, sondern schlicht abgeschnitten) und die Verarbeitung von Gleitkommazahlen ist um einiges komplizierter (vor allem weil der Exponent noch gesondert betrachtet werden muß). Wenn du auf deinem Zielsystem keine double's hast, bleiben dir zwei mögliche Lösungansätze:

    • Gleitkomma-Arithmetik selber nachbauen (viel Spaß dabei ;))
    • Festkommawerte (die letzten n Stellen einer int-Zahl gelten als Nachkomma-Bereich)


  • Genau das ist meine Hauptaufgabe(istn Diplomthema), Theoretisch hab ich da schon informationen. Hab da noch son altes buch 😃 Nur wie gesagt das stehts theoretisch und ich brauch halt die Binär darstellung der Fließkommazahl. Damit ich mir die Mantisse und Exp holen kann.



  • Reichen dir die Ausführungen unter Gleitkommazahl (Wikipedia) aus?



  • Alles schön und gut nur wie gesagt die CPU kann keine Fließkommaarithmetik und was die bei Wiki zeigen um die Binärdarstellung zu erreichen ist Fließkomma.

    Meine Idee war wie folgendes bild zeigt

    http://www.mactech.com/articles/mactech/Vol.15/15.07/AltiVecRevealed/fig04.gif

    im Bereich von

    0-22 Mantisse
    23-30 Exponent
    31 Vorzeichen

    dann hätte ich das was ich brauche. Nur wie komme ich sinnvoll an diese darstellung. Wenn ich ein eingabe wert

    float = 2,54311f
    

    habe



  • Versuch's mal mit reinterpret_cast<> (und Bit-Operationen zur Aufteilung des Wertes).



  • Irgendwie compiliert der das nicht, bekomme immer die Message hier
    cannot convert from 'float' to 'char *' There is no context in which this conversion is possible?!?

    #include<iostream>
    #include <stdio.h>
    #include <conio.h>
    
    using namespace std;
    
    void main()
     {
    	 float f = -1.04f;
    	 long  l = reinterpret_cast<char*>(f);	
    	 cout<< l <<endl;
    	 getchar();
     }
    


  • das char gehört da nicht rein sollte long stehen.



  • Ist auch egal, wenn du etwas als Zeiger reinterpreten willst, musst Du auch einen Zeiger reingeben:

    Quelltyp x;
    Zieltyp* y = reinterpret_cast<Zieltyp*>(&x);
    


  • So hab mich mal registriert weil es doch bissl mehr wurde. Ich hab was gefunden jetzt in Hexadezimal nur leider ist der Code bissl Unverständlich für mich. Die nächste sache wäre das in die Binärdarstellung überführe.

    #define BACC(var, n) *((unsigned char*)&(var) + (n))
    
    void main()
    {
    unsigned char bin_byte;
    float f = 21.13152265f;
    int i;
    
       for(i = 0; i < sizeof(f); i++)
       {
          bin_byte = BACC(f, i);
          printf("0x%02x ",bin_byte);
       }      
    }
    


  • Nicht direkt eine Antwort, aber ich wollte nochmal auf das Makro und den Cast eingehen, denn das geht in C++ schöner und sicherer:

    typedef unsigned char byte; // reine Faulheit, nicht erforderlich
    
    template<typename Type>
    inline byte BACC(Type f, int byteno)
    {
        return *( reinterpret_cast<byte*>( &f ) + byteno );
    }
    


  • Kann mir jemand erklären was diese Zeile macht?

    #define BACC(var, n) *((unsigned char*)&(var) + (n))
    

    So wie ich das verstehe liest der jedes mal 1 Byte (unsigned Char) und Speichert das in var? und n gibt die stellen an. Aber diese Verschachtlung macht mich ein bissl konfus



  • Wo siehst Du eine Zuweisung an var?

    Der Ausdruck nimmt die Adresse von var durch den Operator "&" (wobei die Klammern um var hier unnötig sind). Diese Adresse wird als Zeiger auf unsigned char* (weil char die kleinste adressierbare Einheit ist) uminterpretiert (gecastet). Die Adresse des unsigned char wird dann um n Stellen inkrementiert (in diesem Fall um n kleinste adressierbare Einheiten), um die n-te Einheit von var zu erreichen. Die resultierende Adresse wird dann dereferenziert (Sternchen vor der ersten Klammer) um den Wert der n-ten Einheit von var zu erhalten.

    Schau Dir nochmal die von mir gepostete Funktion an, die ist (IMHO) leichter verständlich, auch wenn dasselbe dabei herauskommt.



  • Schick 🙂 Danke nochmal, eine Frage wieso nimmst du eine Templatefunktion? anstatt

    unsigned char BACC(float f, int byteno)
    {
       return *( reinterpret_cast<byte*>( &f ) + byteno );
    }
    

Anmelden zum Antworten