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



  • Titel is Programm 😃
    Wie kann ich bei der if Funktion kontrollieren ob eine flout Variable eine ganze Zahl ist
    wollte es so lössen nimmt er aber nicht an weil er sagt dass ich die int Variable Zwischenergebniss in eine flout umwandeln würde:

    int Ergebniss
    int Zwischenergebniss
    int ZwischenergebnissReal
    
             for (int i; i<Ergebniss; i++)
             {
                Zwischenergebniss = Ergebniss / i;
                 ZwischenergebnissReal = Ergebniss / i;
                 if (Zwischenergebniss == ZwischenergebnissReal && Zwischenergebniss != Ergebniss && Zwischenergebniss != 1)
                 {
                                       cout << Ergebniss << " IST EINE PRIMZAHL!!!\n";
                                       system("PAUSE");
                 }
    

    wär schön wenn ihr mir schnell helfen könntet

    PS: Zu dem code:
    Will wissen o Zwischenergebniss eine ganze Zahl ist (1, 2, 3, 4, .... ) 😃



  • wollte es so lössen nimmt er aber nicht an weil er sagt dass ich die int Variable Zwischenergebniss in eine flout umwandeln würde

    Ist doch richtig so? Oo
    Also ich weiß nicht, obs nen eleganteren Weg gibt, aber:

    bool is_int (const float &v)
    {
    //1.
    int v2 (v);
    return (v2 == v);
    //oder:
    return (v == static_cast <int> (v));
    }
    

    Wahrscheinlich gibts aber in der math-bibliothek (#include <cmath>) ne schönere und wahrscheinlich effektivere Methode - weil bei meiner Lösung immer 2 Umwandlungen statt finden - eine von float auf int und dann wieder nach float damit er die beiden floats vergleichen kann...

    bb



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


  • Was muss ich bei welchem Wert einsetzen?
    ich meine bei (wert) und bei =wert



  • Da man ja keine Doubles direkt vergleichen soll, hier nochmal eine weitere Variante:

    double eps = 0.0000001;
    if (fabs(static_cast<int>(wert) - wert) < eps)
    


  • greece57 schrieb:

    Was muss ich bei welchem Wert einsetzen?
    ich meine bei (wert) und bei =wert

    Wert ist dein float was du prüfst. Aber davon ganz abgesehen wird es nicht so ohne weiteres funktionieren (Durch die ungenauigkeiten von float wäre zudem ein Deltavergleich angebracht).



  • wert = Zwischenergebniss

    Du setzt natürlich in beiden Fällen die Variable ein, die getestet werden soll.



  • Sorry, hatte nicht bemerkt, dass nur int verwendet wird.
    Hier jetzt eine Version passend zu deinem Code:

    double eps = 0.0000001;
    double x = static_cast<double>(Ergebniss) / i;
    if (fabs(static_cast<int>(x) - x) < eps)
    


  • 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