Bitoperationen an float



  • @ Bashar: Ich werds ausprobieren, aber ich dachte, wenn der Speicher gemeinsam ist und die Länge gleich, sollte der jeweilige Wert von den Typenstandards festgelegt sein.



  • auch mal ne frage in der richtung: wenn ich eine little-endian maschine habe, werden dann auch floats/doubles zwangsläufig falsch herum gespeichert, oder gibt's da keinen zusammenhang (bzw. der c-standard sagt nix dazu)?
    🙂



  • also das einzige was ich jetzt auf die schnelle finden konnte war das, aber das kennt ihr sicher schon

    ANSI-C sieht vor, daß in der Header-Datei float.h symbolische Konstanten bereitgestellt werden, die Auskunft über die Parameter der Arithmetik geben:

    xxx_DIG Genauigkeit: Anzahl der Dezimalstellen
    xxx_EPSILON kleinste Zahl mit 1.0 + xxx_EPSILON != 1.0
    xxx_MANT_DIG Anzahl der Bits in der Mantisse
    xxx_MAX größster Wert
    xxx_MAX_10_EXP größster Exponent (dezimal)
    xxx_MAX_EXP größster Exponent (binär)
    xxx_MIN kleinster Wert
    xxx_MIN_10_EXP kleinster Exponent (dezimal)
    xxx_MIN_EXP kleinster Exponent (binär)

    http://www.imb-jena.de/~gmueller/kurse/c_c++/c623.html



  • ;fricky schrieb:

    nwp2 schrieb:

    Das Problem bleibt aber bestehen.

    aber nur bei typumwandlungen, z.b. uint32_t in char[4] oder sowas, sonst nicht.

    Richtig! Und worum geht es hier? Typumwandlungen! Wir schmeißen ints, floats und chars munter durcheinander.

    IEEE 754, 23 Bits Mantisse, 8 Bit Exponent und irgendwo schwirrt noch ein Vorzeichenbit rum. Wenn man int i = 1 als float interpretiert, hat man dann den Exponenten, die Mantisse oder das Vorzeichen getroffen? Wenn man Mantisse 1.1 mit hidden Bit hat und macht einen Linksshift, kommt dann 1.01 raus? Oder schieben wir das Bit ins Vorzeichen rein?

    ;fricky schrieb:

    auch mal ne frage in der richtung: wenn ich eine little-endian maschine habe, werden dann auch floats/doubles zwangsläufig falsch herum gespeichert, oder gibt's da keinen zusammenhang (bzw. der c-standard sagt nix dazu)?
    🙂

    Gute Frage. Ich würde meinen der C-Standard sagt dazu nichts weiter als dass sich die Operatoren gleich verhalten müssen, egal welche Rehenfolge die Bits und Bytes haben. Wenn floats nicht "falschrum" gespeichert werden wird es ziemlich irritierende Ergebnisse beim Floatshiften im Intstyle geben. Es ist halt nicht vorgesehen dass man floats shiftet.

    Aber schön dass ich noch nicht komplett verwirrt bin und das Problem doch noch erkannt wurde.



  • noobLolo schrieb:

    also das einzige was ich jetzt auf die schnelle finden konnte war das, aber das kennt ihr sicher schon

    ja danke, hift aber leider nix. mir (und dem op wird sicherlich nutzen) geht's um die interne speicherung als folge von bytes.
    🙂



  • nwp2 schrieb:

    ;fricky schrieb:

    nwp2 schrieb:

    Das Problem bleibt aber bestehen.

    aber nur bei typumwandlungen, z.b. uint32_t in char[4] oder sowas, sonst nicht.

    Richtig! Und worum geht es hier? Typumwandlungen! Wir schmeißen ints, floats und chars munter durcheinander.

    IEEE 754, 23 Bits Mantisse, 8 Bit Exponent und irgendwo schwirrt noch ein Vorzeichenbit rum. Wenn man int i = 1 als float interpretiert, hat man dann den Exponenten, die Mantisse oder das Vorzeichen getroffen? Wenn man Mantisse 1.1 mit hidden Bit hat und macht einen Linksshift, kommt dann 1.01 raus? Oder schieben wir das Bit ins Vorzeichen rein?

    deshalb habe ich auch gesagt, das bei floats die Bitoperationen keinen Sinn machen. Wenn ich dem OP verstanden habe, will er die Bits ohne einen festen Sinn (wie etwas bei ints dass ein link shift eine 2^x Multiplikation gleichkommt) manipulieren.



  • ;fricky schrieb:

    auch mal ne frage in der richtung: wenn ich eine little-endian maschine habe, werden dann auch floats/doubles zwangsläufig falsch herum gespeichert...

    ja scheint so als wenns so wär

    hab mal dieses bild verwendet http://upload.wikimedia.org/wikipedia/commons/thumb/d/d2/Float_example.svg/590px-Float_example.svg.png

    und der code schaut so aus

    unsigned int swap32(unsigned int x)
    {
    	return x<<24 | x>>24 |
    		(x & (unsigned int)0x0000ff00UL)<<8 |
    		(x & (unsigned int)0x00ff0000UL)>>8;
    }
    
    int main(void)
    {
    	float x = 0.15625;
    	int *z = (int*)&x;
    	*z = swap32(*z);
        return 0;
    }
    

    vor dem swap32 steht in *z 0x0000203E und danach 0x3E200000 und das ist laut meinem rechner 1111100010000000000000000000000000 sollt schon stimmen oder?



  • supertux schrieb:

    Wenn ich dem OP verstanden habe, will er die Bits ohne einen festen Sinn (wie etwas bei ints dass ein link shift eine 2^x Multiplikation gleichkommt) manipulieren.[/quote]
    naja, der sinn ist wohl, mit dem IEEE-format ein bisschen rumzuspielen, mantisse, exponent usw. verändern und so.
    🙂



  • Bommelmutze schrieb:

    @ Bashar: Ich werds ausprobieren, aber ich dachte, wenn der Speicher gemeinsam ist und die Länge gleich, sollte der jeweilige Wert von den Typenstandards festgelegt sein.

    Ausprobieren hat da nicht viel Sinn, es dürfte in der Regel funktionieren, es ist nur formal nicht definiert. Deshalb sag ich ja, "es sei denn das ist dir egal".



  • Bashar schrieb:

    Bei einer union ist nicht definiert, was passiert, wenn man einen Member schreibt und dann einen anderen liest.
    Das solltest du also nicht tun, es sei denn, das ist dir egal. Die Variante mit dem Zeigercast hat dagegen übrigens definiertes Verhalten.

    Das ist mir in dem Fall wirklich egal, da es funktioniert und für einen Informatikkurs aus 9. - 13. Klässlern leicht nachvollziehbar ist.

    ;fricky schrieb:

    naja, der sinn ist wohl, mit dem IEEE-format ein bisschen rumzuspielen, mantisse, exponent usw. verändern und so.
    🙂

    Das trifft ungefähr was ich vor hatte.



  • Bommelmutze schrieb:

    ... 9. - 13. Klässlern leicht nachvollziehbar ist.

    das lass ich mal so dahin gestellt nicht das die dich dann alle so 😮 anschauen, denk das geht mit ein paar bildchen ala wikipedia schon besser die würd ich auf vorrat mal mitnehmen 😉

    lg lolo



  • Falls noch jemand an dem Quellcode interessiert ist: http://file.qip.ru/file/118107124/64cfce82/Floating_Point_UI.html
    Das C Programm ist mit -std=c99 zu kompilieren, da for-Schleifen, wie in C++, verwendet werden.
    Das C++ Programm hat zusätzsliche eine Multiple Choise Steuerung.


Anmelden zum Antworten