Wie funktioniert Konvertierung von double zu int?



  • Warum parst du die Zahlen beim Datei-Einlesen nicht gleich in ein exaktes Format?



  • Wer Dezimalzahlen ohne Rundungsfehler berechnen will, darf kein double verwenden.
    Entweder verwendet man http://gmplib.org/ oder man rechnet intern mit int's, long's oder long long's und fügt bei der Ausgabe einen '.' ein.

    Aber du hast zum Teil Recht, dass bei deiner Version weniger Rundungsfehler auftreten können.



  • Nexus schrieb:

    Warum parst du die Zahlen beim Datei-Einlesen nicht gleich in ein exaktes Format?

    Falls die Frage an mich geht:
    Die Zahlen sind als double gespeichert.
    Also nicht: 134.46, sondern via:

    fwrite(&doublezahl, sizeof(double), ...



  • Belli schrieb:

    Die Beträge haben zwei zu berücksichtigende Nachkommastellen und sind in der Datei als double-Werte gespeichert.
    ..
    mit
    fwrite(&doublezahl, sizeof(double), ...

    Vielleicht ist es jetzt einfach schon zu spät und ich verstehe dein Problem nicht richtig.
    Okay, war zu spät, gute Nacht 🙂



  • Wenn die Daten binär als double (nicht String) gespeichert sind, kannst du nicht bis zu "." einlesen.

    Aber die Frage ist dann halt: Warum als double speichern, wenn man sich der Rundungsproblematik bewusst ist? Kannst du das mit einem long nicht so einstellen, dass die untersten beiden Dezimalstellen die Nachkommastellen darstellen (:p)? Also quasi Cents als long speichern. Oder sonst auch zwei separate int s oder so.



  • Ja klar. Wenn man (ich) von Anfang an um die Problematik gewußt hätte, hätte man die Werte von vornherein als int - Werte bearbeitet und nur für die Ausgabe/Anzeige ein Komma an die richtige Stelle gesetzt.
    Aber ich habe hier eine Anwendung, die fast 20 Jahre alt ist; von den Rundungsproblemen wurde ich irgendwann viel später überrascht, wahrscheinlich ist das ein Problem, mit dem Programmieranfänger überhaupt nicht rechnen ...



  • Hallo Belli,

    willkommen im Club!

    Fliesskommazahlen (float, double, ...) sind nun einmal viel genauer als Ganzzahlen (int, ...). Man setzt sie deshalb auch vor allem in technischen und wissenschaftlichen Berechnungen ein. Bei Geldbeträgen - wie du gesehen hast - kann es unschöne Unstimmigkeiten geben. Vielleicht musst du mit der übernommenen Datei und den vorhandenen double-Werten keinen grossen Aufwand treiben. Dazu solltest du aber mehr über das die Datei auswertende Programm mitteilen.

    Du hast die Problematik erkannt und bist damit über den Anfänger hinaus gekommen. Der Rest ist 'Softwarepflege' versus 'Neuprogrammierung'. Ein 20 Jahres alte fremdes Programm anpassen zu wollen, ist nicht unbedingt ratsam und muss deswegen im Aufwand sehr sorgfältig durchdacht sein.



  • berniebutt schrieb:

    Hallo Belli,
    Fliesskommazahlen (float, double, ...) sind nun einmal viel genauer als Ganzzahlen (int, ...)...

    Ähmm nein. Fliesskommazahlen sind eben nicht genauer.



  • Fliesskommazahlen (float, double, ...) sind nun einmal viel genauer als Ganzzahlen (int, ...).

    nö. ganzzahlen sind genau(natürlich nur in ihrem wertebereich). fließkommazahlen sind die, die ungenau sind...



  • unskilled schrieb:

    nö. ganzzahlen sind genau(natürlich nur in ihrem wertebereich). fließkommazahlen sind die, die ungenau sind...

    Und eben in dem Wertebereich von Ganzzahlen - also z.B. zwischen 1 und 2 - sind Fliesskommazahlen sehr genau, sonst bräuchte man sie nicht!

    Beispiel:
    - ganzahlige Division 3 / 2 liefert 1
    - Flieskommadivision 3. / 2. liefert 1.5

    Was ist nun genau und was ungenau?

    Aber das lernt man schon im Kindergarten mit der einfachen Aufgabe 3 Äpfel gerecht auf 2 Kinder aufzuteilen. Man braucht dafür ein Messer zum Teilen und trifft es damit nie präzise genau, aber immerhin besser als jedem Kind 1 Apfel zu geben und den 3. Apfel selbst zu nehmen. :p



  • berniebutt schrieb:

    unskilled schrieb:

    nö. ganzzahlen sind genau(natürlich nur in ihrem wertebereich). fließkommazahlen sind die, die ungenau sind...

    Und eben in dem Wertebereich von Ganzzahlen - also z.B. zwischen 1 und 2 - sind Fliesskommazahlen sehr genau, sonst bräuchte man sie nicht!

    Blödsinn. Wenn alle Zahlen zwischen 1 und 2 sind, merkt man sich intern vielleicht nen Offset von 1 und den betragsmäßig größten Exponenten, sodass der Wertebereich der Integer verkleinert durch den Exponenten das Intervall noch ganz überdeckt, wenn man denn die höchste Genauigkeit mit einfachen Mitteln haben möchte.



  • berniebutt schrieb:

    unskilled schrieb:

    nö. ganzzahlen sind genau(natürlich nur in ihrem wertebereich). fließkommazahlen sind die, die ungenau sind...

    Und eben in dem Wertebereich von Ganzzahlen - also z.B. zwischen 1 und 2 - sind Fliesskommazahlen sehr genau, sonst bräuchte man sie nicht!

    Sie sind in keinster Weise "genau". Integer haben exakte Werte und solange man im Wertebereich bleibt, wird auch jede Addition ein exaktes Ergebnis liefern. Letzteres ist für Fließkommazahlen eben schon nicht gegeben. Auch ein grund dafür, warum man wenn man viele Fließkommazahlen addieren will, sie vorher sortieren sollte und beim addieren mit den Kleinsten beginnt, so das die Rechenverluste möglichst gering sind.



  • Michael E. schrieb:

    Blödsinn. Wenn alle Zahlen zwischen 1 und 2 sind, merkt man sich intern vielleicht nen Offset von 1 und den betragsmäßig größten Exponenten, sodass der Wertebereich der Integer verkleinert durch den Exponenten das Intervall noch ganz überdeckt, wenn man denn die höchste Genauigkeit mit einfachen Mitteln haben möchte.

    Wer soll das verstehen mit deiner Float-Arithmetik für integer und dem Gebrauch von Offsets? 😕 Ich nicht!!! 😞 Wozu kennen denn alle Compiler seit Olims Zeiten verschiedene Datentypen wie integer und float???

    Hat jedoch wenig mit Programmierung oder C++ zu tun, sondern eher mit dem Grundlagenwissen der Mathematik. Lernt man nach dem Kindergarten in der Schule!
    Ich programmiere grundsätzlich zuerst im Kopf und wähle danach die geeigneten Methoden aus. Hat mir bisher nicht geschadet. Offsets kannte ich nur aus 8- oder 16-bit-Zeiten die für Adressierung von Speicherbereichen 😡

    @asc: Ja, Integers sind exakt auf eben ganzzahlige Werte. Alles dazwischen geht schlicht verloren, was möglicherweise fatale Wirkung haben kann. Da soll mal jemand bei einer Bank die abgeschnittenen Zinserträge der Kunden zu seinem Gunsten aufaddiert haben - kam richtig was raus - ist aber aufgefallen!



  • berniebutt schrieb:

    Wer soll das verstehen mit deiner Float-Arithmetik für integer und dem Gebrauch von Offsets? 😕 Ich nicht!!! 😞

    Das hast du doch selbst vorgeschlagen:

    Alternativen:
    1. Mit longint in Cent rechnen

    Wozu kennen denn alle Compiler seit Olims Zeiten verschiedene Datentypen wie integer und float???

    Weil es auch Anwendungsbereiche für Fließkommazahlen gibt. Beim Rechnen mit Währungen nimmt man aber besser Festkommazahlen. Diese simuliert man in C++ eben am einfachsten, indem man sich immer nen Exponenten denkt (-> Cents statt Euro).

    Hat jedoch wenig mit Programmierung oder C++ zu tun, sondern eher mit dem Grundlagenwissen der Mathematik. Lernt man nach dem Kindergarten in der Schule!

    Was hat wenig mit Programmierung zu tun und was lernt man direkt in der Schule? Deine Beiträge enthalten leider oft zusammenhangslose Sätze, mit denen ich nichts anfangen kann.

    Offsets kannte ich nur aus 8- oder 16-bit-Zeiten die für Adressierung von Speicherbereichen 😡

    Kein Grund böse zu werden.



  • berniebutt schrieb:

    @asc: Ja, Integers sind exakt auf eben ganzzahlige Werte. Alles dazwischen geht schlicht verloren, was möglicherweise fatale Wirkung haben kann.

    Wie exakt sind denn deiner Meinung nach Fließkommazahlen?

    Alles dazwischen geht schlicht verloren

    Bei Fließkommazahlen auch. Ich wüsste auch nicht, wie man es sonst anstellen sollte 😉

    Edit:

    Und eben in dem Wertebereich von Ganzzahlen - also z.B. zwischen 1 und 2 - sind Fliesskommazahlen sehr genau, sonst bräuchte man sie nicht!

    Rechne mal

    float(int_max)-1
    

    wenn Float und Int gleich viel Speicher belegen.



  • @An Alle: Mannomann - wenn wir Oldie-Programmierer uns mit den seinerzeit schlechteren Compilern um solchen Kleinkram gekümmert hätten, wäre kein Programm gelaufen. Was macht ihr da heute? 😕

    Ein Programm muss zuverlässig laufen. Möglichst mit dem geringsten Aufwand zur Programmierung, nicht viel Laufzeit und Speicher verbraten - und sonst nichts! :p Bin ich hier mit meiner Meinung allein?

    @Fragesteller: Du bist auf dem richtigen Weg.



  • berniebutt schrieb:

    Ein Programm muss zuverlässig laufen.

    Genau da hängts doch mit double 🙄



  • Aaaalso:
    Die Anwendung ist von mir selbst geschrieben worden - damals in C. Ein einigermassen aufwendiges Konsolenprogramm mit Eingabemasken und so weiter. Da die Windows-Konsole nicht mehr 100%ig der damaligen DOS-Konsole entspricht, ich aber beim Jahrtausendwechsel noch mal 'dran musste', sind mittlerweile einige wenige Dinge drin, die sich ein paar Vorteile von C++ zu Nutze machen - es ist aber bei weitem kein C++ - Programm.
    In der Zwischenzeit habe ich mal begonnen, eine Klasse für BCD-Zahlen zu schreiben, beim Dividieren habe ich's glaube ich erst Mal einstellen müssen ... aber in meiner Anwendung würde subtrahieren und addieren auch genügen. Da ich aber nur zwei Nachkommastellen habe, genügt mir eine Konvertierung in Integer vor Addition/Subtraktion; das ist auf jeden Fall um Längen einfacher, als nun in allen relevanten Programmteilen den Datentyp auszutauschen. Naja - eigentlich war meine Ursprungsfrage ja, wie wird (vom Compiler) die Umwandlung durchgeführt, da es ja den Anschein macht, daß eben nicht einfach abgeschnitten wird, sondern gerundet, was für mich die zweite Überraschung (nach den Genauigkeitsproblemen der Fließkommazahlen vor ein paar Jahren) ist.
    Ja - und ich habe eben gelernt, daß es weniger umständlich geht, als ich es angegangen bin (Stichwort: Addition eines geeigneten Epsilon-Wertes).



  • berniebutt schrieb:

    @An Alle: Mannomann - wenn wir Oldie-Programmierer uns mit den seinerzeit schlechteren Compilern um solchen Kleinkram gekümmert hätten, wäre kein Programm gelaufen. Was macht ihr da heute? 😕

    Ich nehm absichtlich ein einfaches Beispiel, das unter MSVC 2010 massiv demonstriert was float & double für Probleme haben (Je nach Typgenauigkeit der Plattform ist dies anzupassen).

    Und ja, dies war schon praxisrelevant und hat Geldbeträge in einer Anwendung verfälscht (Wo es um die Aufteilung von Summen über Kostenstellen ging, damals soviel ich noch in Erinnerung habe mit double).

    #include <iostream>
    #include <iomanip>
    
    int main()
    {
    	float f = 10000000;
    	float f2 = 20000000;
    	for(int i=0; i<10000000; ++i)
    		f += 1;
    	std::cout << std::fixed << f << std::endl << f2;
    }
    

    Wenn ich Genauigkeit brauche wähle ich sicherlich weder float noch double. Für Geldsummen, je nach Rechenregeln (z.B. erinnere ich mich entfernt noch an ein Dokument für Währungsumrechnungen, Fixkomma mit 2 Nachkommastellen für Endsummen und 4 für Berechnungen)...



  • Du könntest im Prinzip auch mit ReadProcessMemory den Wert auslesen. Musst dann halt nur die Mantisse, den Exponent und die Basis einzeln auslesen.


Anmelden zum Antworten