Divisions Problem bei Nachkommastellen



  • Das Problem ist ganz einfach.
    Ich wollte einen Geld betrag ausgeben lassen und brauche eine mit zwei Nachkomme Stellige Zahl.
    Hab mir folgende Funktion dafür geschrieben:

    void fsummeumrechnen(float *nachkommazahl)
    {
    *nachkommazahl = *nachkommazahl + 2.98;
    *nachkommazahl = *nachkommazahl*100;
    int izahl(*nachkommazahl);
    float hilfe(izahl);
    *nachkommazahl = hilfe/100;
    }
    

    Es würde auch klappen, nur berechnet C++ das falsch. Wenn die Variable "hilfe" am Ende z.B. 5599 ist, dann müsste eigentlich 55,99 raus kommen. Macht es aber leider nicht. Es kommt 55,990001697 raus und dann hab ich wieder eine Kommazahl >2, was ich ja durch die Rechnung vermeiden wollte.
    Also wo liegt das Problem??



  • Siehe FAQ - da gibts Funktionen zum runden.

    Das Problem ist die interne Darstellung von Fließkommazahlen. Die können nämlich nur Näherungsweise dargestellt werden - dir führt zu kleinen Ungenauigkeiten - die man am besten wegrundet.



  • Das Problem liegt hier in der internen Darstellung einer Fließkommazahl. Aber es zwingt dich doch niemand alle Nachkommastellen auszugeben.



  • Das Problem ist die interne Darstellung von Fließkommazahlen. Die können nämlich nur Näherungsweise dargestellt werden - dir führt zu kleinen Ungenauigkeiten - die man am besten wegrundet.

    Wozu mach ich dann so eine Funktion, wenn ich das Ergebnis dann nochmal runden muss??

    Es zwingt mich keiner, das stimmt, aber ich möchte das ergebnis in eine Listbox schreiben und da kann ich nicht das cout.precision anwenden. Also muss die gerundete zweistellige Nachkommazahl schon so wie ich sie haben möchte in der Varaible stehen.



  • T-Rex schrieb:

    Es zwingt mich keiner, das stimmt, aber ich möchte das ergebnis in eine Listbox schreiben und da kann ich nicht das cout.precision anwenden. Also muss die gerundete zweistellige Nachkommazahl schon so wie ich sie haben möchte in der Varaible stehen.

    Die Zahl muss sowieso in einen string umgewandelt werden... Ob die Listbox Methoden das jetzt intern machen oder du selber ist dabei dann ja egal -> also einfach selber umwandeln.



  • ??? und dann hab ich einen String mit dem gleichem Problem ?!?



  • T-Rex schrieb:

    ??? und dann hab ich einen String mit dem gleichem Problem ?!?

    Wieso? Du kannst ja runden und dann die restlichen Kommastellen weglassen.



  • UND WIE???????
    Was meinste warum ich so eine "komplizierte" Funktion gebaut hab. Ich hab doch keinen Plan wie ich sonst die Nachkommastellen abschneiden soll.

    Aber danke für die Hilfe?



  • streams und setprecision?
    oder sprintf oder selber schreiben?

    Du sollst ja nicht die Zahl auf 55,2200000000000 bringen, sondern 55,2200000003433 als 55,22 in einen string schreiben.



  • beispiel

    #include <stdio.h>
    
    int main(int argc, char* argv[])
    {
    	float f = 54645.7869875695675896;
    	char szTemp[80];
    
    	sprintf(szTemp, "%.2f", f);
    
    	printf("ausgabe: %s\n", szTemp);
    
    	return 0;
    }
    


  • #include <iostream>
    #include <math.h>
    
    using namespace std;
    
    int()
    {
        double x=23.456789;
    
        cout << floor(x*100)/100;
    
        return 1;
    }
    


  • miller_m schrieb:

    beispiel

    #include <stdio.h>
    
    int main(int argc, char* argv[])
    {
    	float f = 54645.7869875695675896;
    	char szTemp[80];
    	
    	sprintf(szTemp, "%.2f", f);
    	
    	printf("ausgabe: %s\n", szTemp);
    
    	return 0;
    }
    

    😕 Komisches Beispiel. Ist erstmal gar kein C++ und zum zweiten ist es völlig überflüssig erst sprintf und dann printf aufzurufen.

    Ich würde eher zu folgendem tendieren:

    #include <iostream>
    #include <sstream>
    using namespace std;
    
    string cutDecimal(float f, streamsize n) {
      stringstream stream;
      stream.setf(ios::fixed, ios::floatfield);
      stream.precision(n);
      stream << f;
      string str;
      stream >> str;
      return str;
    }
    
    int main() {
      cout << cutDecimal(55.99463537f, 3) << endl;
      cout << cutDecimal(0.005f, 2) << endl;
      cout << cutDecimal(0.004f, 3) << endl;
      cout << cutDecimal(0.f, 0) << endl;
    }
    


  • @MaSTaH
    ich weis das es kein c++ ist, da aber t-rex auch nicht immer in c++ schreibt dacht ich mir poste doch einfach ein ansi-c beispiel.

    und das printf war nur zur verdeutlichung (ausgabe) den wenn er den wert in eine listbox addet wird er wohl den string brauchen. 😉



  • #include <stdio.h>
    
    int main(int argc, char* argv[])
    {
        float f = 54645.7869875695675896;
        char szTemp[80];
    
        sprintf(szTemp, "%.2f", f);
    
        printf("ausgabe: %s\n", szTemp);
    
        return 0;
    }
    

    Was für ein doofes Beispiel...
    Aber es funktioniert 😃 . Bis auf einen Rundungsfehler, da 0.4 trotzdem 1 ist, aber das ist bei meiner Anwendung schon ok.
    Danke!!

    Miller: Immer wenn ich eine Frage hab, kommst du mit deinem print oder scan. Kannst du mir mal erklären wofür die Befehle gut sind? Ich meine ich will es ja verstehen und nicht einfach immer mit Copy&Paste einbauen.



  • printf - Formatierte Ausgabe
    scanf - Formatierte Eingabe

    Aber benutz' bitte streams wenn du schon C++ schreiben willst. Die ANSI-C Alternativen sind nicht typesafe.



  • T-Rex schrieb:

    Was für ein doofes Beispiel...

    kein doofes sondern ein einfaches beispiel 😃 😉

    T-Rex schrieb:

    Miller: Immer wenn ich eine Frage hab, kommst du mit deinem print oder scan. Kannst du mir mal erklären wofür die Befehle gut sind? Ich meine ich will es ja verstehen und nicht einfach immer mit Copy&Paste einbauen.

    erklärung siehe oben oder http://www.c-plusplus.net/c.htm

    @t-rex
    du solltest uns mal sagen bzw. dir im klaren werden in welcher sprache du schreibst und welchen standart du verfolgst. ich meine einmal ist c oder c++ oder bcb/vcl oder winapi pur oder eine mischung aus allem. nicht böse gemeint.



  • In Funktionen, die mit Geldbeträgen zu tun haben, rechne ich intern mit "int" oder "long". Bei allen Inputs wird der Betrag mal 100 genommen, alle Outputs liefern einen "float" oder "double" mit Betrag/100. Dann sind nur noch Divisionen kritisch, da muß ich halt aufpassen, wie ich runden will. Dafür sind aber alle Vergleiche unkritisch, und Fehler durch die interne Darstellung von "float" oder "double" hab ich auch nicht.



  • Ich Programmiere mit dem C++ Borland Builder und Miller weiß das, deshalb denke ich geht das schon in Ordnung mit print.
    Außerdem Funktioniert es ja und so lange noch keine ehler da sind...

    Aber danke für den Tipp :).

    *Edit*
    Stand-art?? Wo ist der unterschied zwischen c++ und Borland c++??
    Ist doch die selbe Sprache oder etwa nicht?? 😕
    Also ich benutze den C++ Borland Builder 5 und versuche mich da an einer Windows Anwendung. Also eine Anwendung die so ein schönes Windows Fenster hat mit Editfelder und Listbox.
    Davor haben wir in der Schule mit dem Konsolen experten rum getüfftelt. Die eingabe ist aber sehr umständlich. Dieses Jahr nehmen wir in der Schule objektorientierte Programmierung durch und haben eben die Windows Anwendungen angefangen, die mich gleich begeistert haben.
    Zum testen nehme ich der einfach halber immer noch den Konsolen Experten her, aber das eigentliche Programm soll dann eben die Anwendung sein. Der KE ist leichter für schnelle ein und ausgaben.


Log in to reply