float zu int -> cout gibt etwas anderes aus als wenn es zuerst einer Variable zugewiesen wird



  • Der Titel sagt schon alles.

    float f = 3.6f;
    
    cout << f * 10.0f << endl;
    
    unsigned int uif = f * 10.0f;
    
    cout << uif << endl;
    

    Ausgabe:
    36
    35

    😕



  • Da kommt bedingt durch die Ungenauigkeit von Fließkommazahlen 35.9999... heraus, wird also zu 35 abgerundet.
    Wenn du vorher noch numeric_limits<float>::epsilon() addierst, sollte das richtige Ergebnis herauskommen.
    Und nimm am besten double, wenn es keinen guten Grund dagegen gibt.



  • float f = 3.6f;
    
    cout << static_cast<int>(f * 10.0f) << endl;
    
    unsigned int uif = f * 10.0f;
    
    cout << uif << endl;
    

    Ausgabe:
    35
    35

    Warum allerdings 35 und nicht 36, kann ich auf die Schnelle nicht sagen.



  • Mit double funktionierts.

    Ich möchte double nämlich als long speichern, da ich aus dem WinAPI die Interlocked-Funktionen für Kommazahlen verwenden möchte, die nehmen aber nur long an.
    Deshalb dachte ich mir (da ich eh nur kleinere Werte brauche, und nur mit einer Nachkommastelle), die Eingabe mit 10 zu multiplizieren und dann bei der Ausgabe wieder durch 10 zu teilen...


  • Mod

    Multiplizier lieber mit Potenzen von 2, das dürfte besser funktionieren.



  • Nanyuki schrieb:

    Wenn du vorher noch numeric_limits<float>::epsilon() addierst, sollte das richtige Ergebnis herauskommen.

    Kommt mir wie Voodoo vor. Epsilon ist viel zu klein, um in dem Wertebereich etwas zu bewirken.



  • Bashar schrieb:

    Nanyuki schrieb:

    Wenn du vorher noch numeric_limits<float>::epsilon() addierst, sollte das richtige Ergebnis herauskommen.

    Kommt mir wie Voodoo vor. Epsilon ist viel zu klein, um in dem Wertebereich etwas zu bewirken.

    Könnte klappen.

    float f = 3.6f; 
    cout << f * 10.0f << endl; 
    unsigned int uif = f * 10.0f; 
    cout << uif << endl;
    

    kann der kumpel innendrin ja gar nicht und denkt sich vielleicht

    float f = 3.59999999999999532f;//nächstbeste darstellbare zahl um 3.6
    cout << f * 10.0f << endl; 
    unsigned int uif = f * 10.0f; 
    cout << uif << endl;
    


  • Schon klar, soweit die Idee ... aber Epsilon ist trotzdem zu klein dafür 🙂

    Epsilon ist die kleinste Zahl, so dass 1+Epsilon > 1 ist. Das heißt, 1 ist 1.0000*2^0 und 1+Epsilon ist 1.0001*2^0 (mal float der Anschaulichkeit halber mit 4 Binärstellen angenommen), Epsilon muss folglich 1*2^-4 sein. Jetzt nimmst du beispielsweise 2+Epsilon, also 1.0000*2^1 + 1*2^-4 und bekommst 1.0000(1)*2^1. Das in Klammern war das Epsilon ...

    Wenn, dann sollte man 3.6*epsilon drauf addieren.



  • Bashar schrieb:

    Wenn, dann sollte man 3.6*epsilon drauf addieren.

    ne... (f+eps)*10.f...

    bb



  • Nomen est omen



  • Bashar schrieb:

    Nomen est omen

    um bei deinen 4 stellen zu bleiben:
    3.5999 * 10 = 35.9990
    wenn man jz 3.6*0.0001 draufaddiert, bekommt man eben nur 35.9993
    das ist genau so wenig 36 wie 35.9990...

    bb



  • unskilled schrieb:

    Bashar schrieb:

    Nomen est omen

    um bei deinen 4 stellen zu bleiben:
    3.5999 * 10 = 35.9990

    Meine 4 Stellen sind binär. Im Dezimalsystem sind 3.6 und 1 in derselben Größenordnung, im Binärsystem nicht. Versuch dein Beispiel doch mal mit 13.599.

    wenn man jz 3.6*0.0001 draufaddiert, bekommt man eben nur 35.9993
    das ist genau so wenig 36 wie 35.9990...

    Das wird auch vorher drauf addiert, nicht erst danach. Also (f+f*eps)*10. Das ist auch im ganzen Thread bisher so gesagt wurden, wie kommst du darauf, dass von nachträglicher Addition die Rede ist?



  • oh - sry... war wohl beim lesen ein wenig abgelenkt ><

    bb



  • Nanyuki schrieb:

    Und nimm am besten double, wenn es keinen guten Grund dagegen gibt.

    Das verschiebt doch das Problem nur.

    Wenn man nachher eine ganze Zahl will, wie wärs mit Runden?


Anmelden zum Antworten