Dezimal zu Bruch?



  • Hi,

    wie kann man aus ner Dezimalzahl (z.B. 0,75) einen Bruch machen (3/4)?

    Ich dachte da an so ne Funktion:

    void dezZuBruch (int *zaehler, int *nenner, double dezimalzahl)
    

    Wie macht man sowas? Der Taschenrechner kanns ja auch?



  • 0,75 sind 75/100, einfach immer die anzahl der nachkommastellen mit ner eins untern bruchstrich, und die nachkommastellen selber in zähler. dann noch kürzen... kann ja nich so schwierig sein (ggt von beiden zahlen suchen)



  • ############ schrieb:

    ...

    void dezZuBruch (int *zaehler, int *nenner, double dezimalzahl)
    

    ...

    das ist alles reine mathematik, dürftest du eigentlich auf hunderten von seiten im netz finden (dürfte 5. klasse gewesen sein 😉 )

    deine formel selbst verstehe ich aber nicht, du gibst der funktion 'deZuBruch' einen zähler, einen nenner und eine dezimalzahl. was willst du dann noch errechnen lassen, wenn du ihm den zähler und den nenner schon gibst?

    besser wäre doch etwas in der art wie:

    int dezZuBruch (double dezimalzahl)
    {
     bla_bla_blub;
     return zaehler && nenner
    };
    

    //edit schreibfehler beseitigt



  • enno-tyrant:
    deine formel selbst verstehe ich aber nicht, du gibst der funktion 'deZuBruch' einen zähler, einen nenner und eine dezimalzahl. was willst du dann noch errechnen lassen, wenn du ihm den zähler und den nenner schon gibst?

    Nein, er gibt einen Zeiger auf den Nenner und den Zähler, in die er dann den Nenner und Zähler schreibt - was auch durchaus Sinn macht.
    Hingegen weiß ich nicht was dein

    return zaehler && nenner

    bewirken soll, da && die logische UND Verknüpfung ist und nur 1 oder 0 zurückliefert. Und auch die binäre & Operation wäre hier nicht angebracht. Wenn dann müsste man ein struct mit zwei ints zurückliefern.



  • Kannst es ja mal hiermit probieren. Ist nur nicht so sauber programmiert, ich hab zum Beispiel ausgenutzt, bzw. unsauber umgangen, wie sich double-Werte verhalten

    #include <iostream>
    #include <cmath>
    using namespace std;
    
    const double Ungenauigkeit = 0.0000000002;
    
    // Prüft, ob eine Zahl (double) eine ganze Zahl ist
    bool IstGanz (double Zahl)
    {
        if((Zahl - static_cast<int>(Zahl) - Ungenauigkeit < 0) && (Zahl - static_cast<int>(Zahl) + Ungenauigkeit > 0))
        {
            return(true);
        }
        else
        {
            return(false);
        }
    }
    
    class Bruch
    {
        int Nenner, Zaehler;
        void Kuerzen (void);
        public:
            Bruch (int Nenner_, int Zaehler_);
            Bruch (double Zahl);
            operator double (void);
            int GetNenner (void)
            {
                return(Nenner);
            }
            int GetZaehler (void)
            {
                return(Zaehler);
            }
    };
    
    // Konstruktor für Bruch, der einen double in einen Bruch umwandelt
    // (Erst die Komma-Zahl in einen Bruch umwandeln und dann kürzen)
    Bruch::Bruch(double Zahl)
    {
        bool Negativ = false;
        if(Zahl < 0)
        {
            Zahl = -1*Zahl;
            Negativ = true;
        }
        int i = 1;
        while(!(IstGanz(Zahl*pow(static_cast<double>(10),static_cast<double>(i)))))
        {
            ++i;
        }
        Zaehler = Zahl*pow(static_cast<double>(10),static_cast<double>(i)) + Ungenauigkeit;
        Nenner = pow(static_cast<double>(10),static_cast<double>(i));
        Kuerzen();
        if(Negativ)
        {
            Zaehler = -1*Zaehler;
        }
    }
    
    Bruch::Bruch(int Nenner_, int Zaehler_)
    {
        Nenner = Nenner_;
        Zaehler = Zaehler_;
        Kuerzen();
    }
    
    Bruch::operator double (void)
    {
        return(static_cast<double>(Zaehler)/Nenner);
    }
    
    // Kürzt den Bruch, indem ein gemeinsamer Teiler gesucht wird,
    // durch den dann geteilt und wieder gekürzt wird
    void Bruch::Kuerzen (void)
    {
        for(int i = 2; ((i <= Nenner) && (i <= Zaehler));++i)
        {
            if((Nenner%i == 0) && (Zaehler % i == 0))
            {
                Nenner /= i;
                Zaehler /= i;
                Kuerzen();
            }
        }
        return;
    }
    
    int main (void)
    {
        double Zahl = 0.0;
        do
        {
            cout << "Bitte eine Zahl eingeben, die in einen Bruch umgewandelt werden soll" << endl;
            cin >> Zahl;
            Bruch temp = Zahl;
            cout << temp.GetZaehler() << "/" << temp.GetNenner() << endl;
        }while(Zahl != 0);
        cin.clear();
        cin.ignore(std::cin.rdbuf()->in_avail());
        cin.get(); 
        return (0);
    }
    

    Mfg

    Felix



  • feines teil, aber noch nicht sehr ausgereift:

    gib mal 0.33333333333333 ein, sollte eigentlich 1/3 ergeben, tuts aber net 😉 das Programm hängt sich in einer Endlosschleife auf.



  • Und wenn du schon dabei bist frag doch einfach mal google was Euklid mit der ganzen Sache zu tun hat 😉



  • *** schrieb:

    feines teil, aber noch nicht sehr ausgereift:

    gib mal 0.33333333333333 ein, sollte eigentlich 1/3 ergeben, tuts aber net 😉 das Programm hängt sich in einer Endlosschleife auf.

    0.33333333333333 != 1/3

    aber endlosschleife is natürlich auch nix 😉



  • mata schrieb:

    0.33333333333333 != 1/3

    Vielleicht meinte er 0,33333333333333 Periode.
    Oder 0, Periode 33333333333333?
    Verflixt, gab's da nicht ne Regel? 😃



  • finix schrieb:

    mata schrieb:

    0.33333333333333 != 1/3

    Vielleicht meinte er 0,33333333333333 Periode.
    Oder 0, Periode 33333333333333?
    Verflixt, gab's da nicht ne Regel? 😃

    jo, die gabs.
    bei 0.123412341234 peridoe rechne 1234/9999 (statt 10000).



  • volkard schrieb:

    finix schrieb:

    mata schrieb:

    0.33333333333333 != 1/3

    Vielleicht meinte er 0,33333333333333 Periode.
    Oder 0, Periode 33333333333333?
    Verflixt, gab's da nicht ne Regel? 😃

    jo, die gabs.
    bei 0.123412341234 peridoe rechne 1234/9999 (statt 10000).

    Meinte hauptsächlich die Sprachregel - Periode vor der Periode oder Periode nach der Periode 😉



  • finix schrieb:

    volkard schrieb:

    finix schrieb:

    mata schrieb:

    0.33333333333333 != 1/3

    Vielleicht meinte er 0,33333333333333 Periode.
    Oder 0, Periode 33333333333333?
    Verflixt, gab's da nicht ne Regel? 😃

    jo, die gabs.
    bei 0.123412341234 peridoe rechne 1234/9999 (statt 10000).

    Meinte hauptsächlich die Sprachregel - Periode vor der Periode oder Periode nach der Periode 😉

    danach eigentlich. aber das ist dann so uneindeutig. bei "null komma eins sechs zwei periode" weiß man einfach nicht, wo die periode beginnt. deswegen sagen leuite, die um deutlichkeit bemjüht sind, gerne "null komme eins sechs periode zwei". man kann sich auch dran gewöhnen. ist einfach netter stil, so wie der querstrich im runterstrich im kleinen q, damit man es nicht mit der 9 verwechselt. oder ableitungsregeln mit f und g (gut unterscheidbar) statt mit u und v.



  • Was hat es mit der Ungenauigkeit auf sich die hier mit verrechnet wird?

    const double Ungenauigkeit = 0.0000000002;

    // Prüft, ob eine Zahl (double) eine ganze Zahl ist
    bool IstGanz (double Zahl)
    {
        if((Zahl - static_cast<int>(Zahl) - Ungenauigkeit < 0) && (Zahl - static_cast<int>(Zahl) + Ungenauigkeit > 0)
    


  • Mynijo schrieb:

    Was hat es mit der Ungenauigkeit auf sich die hier mit verrechnet wird?

    const double Ungenauigkeit = 0.0000000002;

    // Prüft, ob eine Zahl (double) eine ganze Zahl ist
    bool IstGanz (double Zahl)
    {
        if((Zahl - static_cast<int>(Zahl) - Ungenauigkeit < 0) && (Zahl - static_cast<int>(Zahl) + Ungenauigkeit > 0)
    

    SO hab jetzt herausgefunden das diese Genauigkeit auftreten kann. Weiß jemand wieso genau sie auftritt... Ich habe bis jetzt nur gelesen das dies durch den Prozessor passieren kann aber gibts da nicht noch einen anderen Grund?



  • wir hatten das Thema Gleitkommazahlen zu Bruch schon mal im Forum ... (Wow schon fast 6 Jahre her)
    Und dieser Thread ist noch älter!



  • bool IstGanz (double Zahl) 
    {
        return std::floor(Zahl) == Zahl;
    }
    

    ?
    (Ungetestet)



  • Die Ungenauigkeit tritt aufgrund von Gleitkommazahlen auf, per Definition.

    Du/Man/Computer kannst nicht mit einer endlichen Länge von Gleitkommazahlen jede Dezimale Zahl genau darstellen.

    Ints lassen sich 100%ig genau darstellen. Späße mit Nachkommaanteilen von Zweierpotenzen(2^0, 2^-1, 2^-2, 2^-3 ...; oder anders ausgedrückt: 0, 0.5, 0.25, 0.125, 0.0625...) auch. Genauso jegliche Summen eben dieser (z.B. 0.75).

    (Vermeintlich einfache) Zahlen wie 0.2 klappen aber nicht mehr. Wenn du das mal auf dem Papier nachrechnest wirst du merken, dass du beliebig genau an diese Zahl drankommst, aber sie nie genau treffen wirst. Das heisst, umso genauer du sein willst, desto mehr Bits/Stellen brauchst du. Ein Computer hat gewöhnlich aber nur eine feste Wortbreite (z.B. 32 oder 64 Bit, manchmal intern auch 80 Bit) und rechnest daher ungenau.

    Bei dem Fall, den du zitiert hast, kann es passieren, dass die Kommazahl nicht genau eine Ganzzahl ist (z.B. 355.0000000000000000001049 oder 354.999999999999999999999999353), daher wird in den Vergleich eine Ungenauigkeit eingerechnet, die diesen Fehler wieder wettmachen soll.

    Nachtrag: Sämtliche Zahlenwerte sind einfach so spontan ausgedacht und halten wahrscheinlich einer exakten Berechnung nicht stand. Es sind lediglich Beispielwerte, was passieren kann.

    Nachtrag Nummer2: Die Ungenauigkeit der Nachkommastellen (z.B. 0.2) kann sich durch den Exponenten der Fließkommazahl auch auf eigentlich ganze Zahlen verschieben: 0.2 * 1000000000000000 = 200000000000000, aber weil 0.2 schon ungenau war und sich der Computer nur den Exponenten und die Mantisse (halt die 0.2) merkt, können da auch Fehler auftauchen.



  • Skym0sh0 schrieb:

    Ints lassen sich 100%ig genau [in Gleitkommazahlen] darstellen.

    Gilt nur, wenn die Mantisse der Gleitkommazahl so lang ist wie der Integer. 32-Bit-Ints passen nicht unbedingt in 32-Bit-Floats und 64-Bit nicht immer in 64-Bit-Doubles, deshalb gibt es auch eine "Possible loss of precision"-Warnung, wenn man implizit ints in floats konvertiert.



  • Ich meinte damit eigentlich richtige Ganzzahlen als int gespeichert.


Anmelden zum Antworten