Problem bei if Funktion: wie kontolliere ich ob Variable ganze Zahl ist



  • Da double üblicherweise auch deutlich grössere Werte als int annehmen kann:

    double epsilon = ...;
    double int_part;
    double frac_part = modf(x, &int_part);
    if (fabs(frac_part) < epsilon)
        buy_yourself_a_cookie();
    


  • ok danke an alle ich hab

    MiP schrieb:

    if (static_cast<int>(wert) == wert)
    

    benutzt
    trotzdem danke an alle
    (programm läuft einwandfrei)



  • std::abs(floatVar-(int)floatVar)>std::numeric_limits<float>::epsilon



  • greece57 schrieb:

    ok danke an alle ich hab

    MiP schrieb:

    if (static_cast<int>(wert) == wert)
    

    benutzt
    trotzdem danke an alle
    (programm läuft einwandfrei)

    Hast du das ausgiebig getestet?
    Ich würde als Testfall z.B. mal 5000000000.0 empfehlen (== 5e9).

    Oh, hustbaer hat schon weiter oben auf dieses Problem hingewiesen. Da hab ich wohl geschlafen.



  • Christoph schrieb:

    Hast du das ausgiebig getestet?

    Mit 100.0000000000000000001 %iger Sicherheit nicht 😉 (Sonst würde er sich auch mal mittels google davon überzeugen warum man keine direkten Vergleiche von Gleitkommazahlen macht, und dann würde er auch nicht den Weg des geringsten Widerstandes, sondern auch mal einen steinigen, sofern das dann dafür richtig ist).

    cu André
    P.S: @Christoph : Frag dann aber bitte auch nicht wegen den (irgendwann auftauchenden) Fehlern.



  • besteht hier denn überhaupt das "gleitkommavergleich" problem? er vergleicht ja nie zwei gleitkommawerte und einen gleitkommawert de eine ganze zahl darstellt ist doch direkt representierbar oder?



  • Das Problem des "Gleitkommavergleichs" ist hier gegeben, da er ja, wie in der Frage zu lesen ist, das Ergebnis einer Division prüfen möchte, ob es eine Gleikommazahl ist oder nicht.

    Nenner und Zähler der Division sind beides urprünglich Integer. Damit dürfte wohl die Problematik entfallen, das das Ergebnis grösser wird als der Wertebereich des Integers.



  • aber sowas wie

    float a = 3.0f;
    int b = 3;
    
    if(a == b)
    	...
    

    wird doch immer zutreffen oder? Und da der vergleich nur klappen muss wenn die zahl ohne nachkommastellen darstellbar ist versteh ich nicht wieso man den vergleich über epsylon machen muss...

    im float steht jetzt ja 3.0 und nicht 2.9999983453253 irgendwas



  • Also so weit ich das hier überschauen kann, braucht man hier keinen epsilon-vergleich, da die Zahl davor ja kopiert wird...

    Ich würd den Vergleich mit Hilfe eines unions`s machen...
    Dann einfach die Potenz mit der Zahl an sich vergleichen..
    Ist eleganter als 100de Male hin und herrechnen find ich ^^

    also:

    struct my_float
    	{
    		signed char exponent;
    		unsigned char mantisse[3];
    //exponent == 127 => unendlich
    //exponent == -128 => 0
    	};
    
    union proof_union
    	{
    		float value;
    		my_float bytes;
    	};
    

    Vll hat ja irgendwer lange Weile und macht dir ne Funktion draus oder so ^^

    bb

    //edit:
    http://books.google.de/books?id=EdUkA4hmltUC&pg=PA169&lpg=PA169&dq=cpp+float+mantisse+&source=web&ots=IiFa8tRDov&sig=yDzBwxqTMEdWHDjAJoLrhJ9slQA&hl=de&sa=X&oi=book_result&resnum=6&ct=result

    hab gerad ma mit dem Algo bissl rumprobiert...
    Aber irgendwie bin ich zu doof : /
    Also das, was da rauskommt kann immer ne so recht sein : /



  • Sry für Doppelpost...

    Ich hab mir jz (mehr oder weniger mit C&P bzw abschreiben) das hier zusammgebastelt:

    #include <iostream>
    
    using namespace std;
    
    struct FTyp
    	{
    		unsigned man1 : 16;
    		unsigned man2 : 7;
    		unsigned exp : 8;
    		unsigned Vz : 1;
    	};
    
    union my_float
    	{
    		float f;
    		FTyp b;
    	};
    
    bool is_int (const float &val)
    	{
    		my_float v; v.f = val;
    
    		long int mantisse (((long int)v.b.man2 << 16) | v.b.man1 | 0x8000000L);
    		signed int exp (v.b.exp-127);
    
    		/*
    		kein Plan, wies weitergehen soll ><
    
    exponent == 127 => unendlich
    exponent == -128 => 0
    		*/
    		return false;
    	}
    
    int main (int argc, char* argv[]) 
    	{
    		const bool a (is_int (6.0f));
    	}
    

    Aber irgendwie kommen für die Mantisse immer elend große Zahlen raus 😞
    Irgendwie versteh ich auch nicht so ganz, was genau hier passiert:

    long int mantisse (((long int)v.b.man2 << 16) | v.b.man1 | 0x8000000L);
    

    Wär nett, wenn sich jmd erbarmen würde, das zu erklären : )

    Aber ich versuchs einfach erst ma selbst:

    long int mantisse
        (
            (
                (long int) //warum reicht hier kein normaler int?
                    v.b.man2 << 16 //16 stellen nach links verschieben, weil danach noch 2 "lower" Bytes kommen
            )
            | //das or ist klar und dessen Bedeutung auch
            v.b.man1 //auch klar...
            | 0x8000000L //das hier aber nicht ><
        );
    

    Und wie gesagt: Das Ergebnis versteh ich auch nicht...

    val == 6.0000000
    v . man2 == 64
      . man1 == 0
      . exp == 129
      . Vz == 0
    Mantisse == 138412032
    exp == 2
    

    Mit den Werten komme ich niemals auf die 6,0 : /

    Danke schon mal, bb

    //edit: hatte rechts statt links geschrieben ><



  • unskilled schrieb:

    Und wie gesagt: Das Ergebnis versteh ich auch nicht...

    val == 6.0000000
    v . man2 == 64
      . man1 == 0
      . exp == 129
      . Vz == 0
    Mantisse == 138412032
    exp == 2
    

    Mit den Werten komme ich niemals auf die 6,0 : /

    Wenn man die Mantisse in binär hinschreibt, bekommt man
    man2 = 1000000
    man1 = 0000000000000000

    Oder zusammen, in der richtigen Reihenfolge (zuerst man2, dann man1):
    10000000000000000000000

    Die Mantisse interpretiert man als Binärbruch, also steht das für
    0.1 (binär!)
    also
    0.5 (dezimal).

    Wegen der Normalisierung muss man 1 draufaddieren um den tatsächlichen Wert der Mantisse zu erhalten, das ergibt 1.5.
    Schließlich ist der Exponent 2, also ist das Ergebnis 1.5 * 2^2 = 1.5 * 4 = 6.



  • Danke erst mal : >

    Christoph schrieb:

    Oder zusammen, in der richtigen Reihenfolge (zuerst man2, dann man1):
    10000000000000000000000

    ok - so weit is klar : >

    Christoph schrieb:

    Die Mantisse interpretiert man als Binärbruch, also steht das für
    0.1 (binär!)
    also
    0.5 (dezimal).

    Wieso ist 10000000000000000000000
    0.1b ?

    Ich würde ja mal raten, dass es immer 0,... ist (mit normalisierung also 1,...)

    und die binärfolge von oben muss man wahrscheinlich (wie das so üblich ist) andersrum lesen, dann würde ich auch die 1 kapieren...
    also:

    10000000000000000000000
    =>
    00000000000000000000001
    | | | | | | | | |   | |
        ...         64  4 1
    

    Danach ist auch wieder klar - nur da bin ich mir alles andere als sicher ^^

    Danke scho ma und sry fürs dumm Stellen ^^
    (zum googlen hab ich anscheind au ne so das Talent 😉 )



  • Nenner und Zähler der Division sind beides urprünglich Integer. Damit dürfte wohl die Problematik entfallen, das das Ergebnis grösser wird als der Wertebereich des Integers.

    Dann soll er doch lieber gleich (a % b) == 0 checken, nicht?


Anmelden zum Antworten