Visual C vs CBuilder, habe "gravierenden" Wert Unterschied



  • Ich glaube nicht das du Lust hast mehrere hundert Zeilen Berechnung durchzugehen 🙄 zumal das absolut garnichts nutzt, ich sagte ja bereits das der Quelletxt 1:1 kopiert wurde. Meine Frage war ja nun lediglich, ob es eine bestimmte Einstellung in CBuilder gibt womit man "berechnungen" beeinflussen kann.

    Da der Rechner der gleiche ist und 100% der selbe Quellcode muss es ja "lediglich" am Compiler hängen.



  • @Joe_M.! Aber Floatingpoints werden von der Hardware (genauer FPU) berechnet und "geschätzt" (hab ich ja auch noch nie gehört, würde eher sagen "ungenau"). Deshalb müsste diese auf dem gleichen PC immer gleich ungenau sein.

    Aber ich kann mir eher vorstellen, das die Library-Implementierung der Compiler für die String-Ausgabe einen Unterschied machen. VC6 hat die Dinkumware-Implementierung und Borland eine ganz andere. Und bei Floats werden halt andere Formatierungen genutzt.



  • peter-san schrieb:

    Ich glaube nicht das du Lust hast mehrere hundert Zeilen Berechnung durchzugehen 🙄 zumal das absolut garnichts nutzt, ich sagte ja bereits das der Quelletxt 1:1 kopiert wurde. Meine Frage war ja nun lediglich, ob es eine bestimmte Einstellung in CBuilder gibt womit man "berechnungen" beeinflussen kann.

    Da der Rechner der gleiche ist und 100% der selbe Quellcode muss es ja "lediglich" am Compiler hängen.

    Das dürfte aber halt nur die Ausgabe sein, also die Konvertierung von float nach String. Die Berechnung müsste trotzdem immer gleich sein.

    Ich würde mir da also keine großen Gedanken machen.

    Wenn du die gleiche Ausgabe haben willst, solltest du evtl. für beide Compiler die gleiche Library benutzen. Z.B. STLport.



  • Wäre nicht schlecht, wenn du mal die String-Ausgabe zeigst. Also welche Klassen/Funktionen werden genutzt, um floats auszugeben?



  • Hallo,

    hast Du eventuell mal die Möglichkeit, einen Zahlenwert der bei dem Vergleich abweicht, mit printf und ohne Formatierung irgendwo auszugeben? Oder aber mal mit sprintf in einen Puffer und diesen dann ausgeben (Debugger):

    char puffer[100];
    float wert;
    
    sprintf(puffer,"Wert: %f", wert);
    

    Zwar nicht der sauberste Text, aber zum debuggen sollte es reichen.

    Dann könnte man sehen, ob denn die unformatierte Gleitkommazahl gleich ist oder nicht. Man sieht dann, ob eine andere Berechnung die Ursache oder die Stringformatierung der Pferdefuß ist...

    VG Pixfreak



  • Es könnte auch an durchgeführten Optimierungen liegen. Oder das die Operationen, compilerbedingt, in einer anderen Reihenfolge stattfinden.

    Der einzige mir bekannte Weg, sämtlichen 'Fließkommadatentypenungenauigkeiten' aus dem Weg zu gehen, ist entweder nur Integerdatentypen zu verwenden, oder eine entsrpechende Bibliothek zu kaufen. Normalerweise sind die aber recht teuer.

    Ich vermute weiterhin die mangelnde Möglichkeit, Fließkommazahlen exakt abzubilden als 'Fehlerquelle'.



  • Diese Ausgabe kam schon nach etligen hundert durchläufen.
    Allgemein macht man die Beobachtung, das ab der dritten Kommastelle die Zahl anders ist. Man könnte jetzt vielleicht sagen, das man zum verhindern der Aufsummierung von Fehlern, einfach immer ab der dritten Kommastelle abschneidet, also 0 setzt.

    Was wäre dafür denn in euren Augen die beste Methode?

    Die Methode halte ich für zeitraubend, da die Berechnung mehr als 100.000 mal durchgeht.

    float fzahl = 1234.5678;
    int rund = (int)(fzahl * 100.0); // Erg: 123456
    fzahl = rund / 100.0;

    CBuilder macht dann daraus 1234.56005641275

    was ja ok wäre, da genug Luft, aber ist das ne optimale Umwandlung oder gehts auch anders schneller?



  • Hallo,

    wäre es denn so schwer einfach die zahlen in einen Integer-datentyp zu überführen? bei der ausgabe kannst du doch dann immer noch auf nachkommastellen "umrechnen".

    Habe hier in einer warenwirtschaftssoftware das gleiche problem mit "ungenauigkeiten", besonders bei der berechnung der steuern. Dort wird es einfach mit einem 64Bit-Integertyp gelöst, von dem dann einfach die letzten 4 stellen als nachkommastellen angenommen werden. Die entsprechenden formatierungen werden dann bei der ausgabe erledigt...

    mfg

    Frank



  • und wie soll das bei 3/2 funktionieren?



  • Hallo,

    3/2 = 1,5 wo ist das Problem?

    Du meinst sicher so sachen wie 1/3. Die sind aber auch bei float nicht "genau". das würde wohl nur mit speziellen bibliotheken funktionieren....

    oder hab ich das nu falsch verstanden?



  • Nun ist der Groschen ähm Euro gefallen...

    3/2 ergibt natürlich eine fließkommazahl. die kannste so nicht in einen Integerwert speichern. Aaaaber....

    ... wenn du einen Inegertyp nimmst, und definierst "letzten 4 stellen sind nachkomma" dann würde deine rechnung 3/2 inetwa 15000 ergeben (als int).

    grob gesagt, rechne alle werte mal 10000, nur bei der ausgabe teilst du sie durch 10000... und schon hast du nur noch glatte zahlen zum rechnen...

    es hängt dann nur noch von dir ab, wie groß du den integertyp wählst (bei mir 64bit) und wieviele stellen du als, nennen wie sie virtuelle, nachkommastellen definierst...



  • Das jetzige Programm umzuschreiben wäre irrsinnig, ist einfach zu gigantisch gross, aber ich werde das mal im Hinterkopf für andere Programme behalten. Danke für die Hilfe 🙂



  • Mit wieviel Byte arbeitet das CBuilder float? 4Byte oder doch mehr?
    Inwiefern unterscheidet es sich vom DOS float?



  • Hallo.

    meine vier Byte, wenn ich richtig gelesen habe. sizeof(float) ist dein Freund, der zeigt es an.

    Klar, wenn Du Dir mal den Aufbau der float oder double Variablen ansiehst, muss die Genauigkeit doch auf der Strecke bleiben, denn mit vier Byte Integer kann ich einen ganz exakten Wert darstellen, mit float nur immer eine Annäherung.

    Frage am Rande: Wer sagt eigentlich, dass die VS Werte richtig sind? Ich hab mal ein Programm zur Berechnung und Erstattung Mineralölsteuer geschrieben. Da kam auch der float Typ zum Einsatz. Dass Zollamt wies uns irgendwann mal darauf hin, dass wir immer ein paar Cent zu wenig Erstattung eingereicht haben. Dies lag an Rundungsfehlern im Typ float. Wir haben dann alles auf integer umgestellt, wie der andere Kollege im Forum. Jetzt stimmt es auf den Cent genau!

    Im Informatik Unterricht in grauer Schulvorzeit haben wir mal eine Klasse geschrieben, die mit insgesammt einhundert Stellen arbeitete, ob Nachkomma oder nicht, es waren hundert. Wir haben die Rechenschritte von Hand implentiert. Gut sollte auch didaktisch wertvoll sein, langsam aber genau.

    VG Pixfreak



  • peter-kun schrieb:

    Mit wieviel Byte arbeitet das CBuilder float? 4Byte oder doch mehr?
    Inwiefern unterscheidet es sich vom DOS float?

    kann sein dass da ein unterschied ist. änder' doch alle 'floats' in 'double', dann ist es vielleicht gut (ist nicht so schwer, suchen und ersetzen in mehreren file haben die IDEs ja eingebaut).



  • Ich mache eine Rechnung ala ((x-y)*(a-b)/(c-y))+z und erhalte bei gleichen Ausgangsvariablen in CBuilder und VisualC zwei verschiedene Ergebnisse. Minimal anders, aber das reicht natürlich um in einer Iteration das Ergebnis gehörig zu verfälschen. Und TurboC und VisualC sind wohl identisch und Handrechnung mit CALC.EXE ergibt ihr Ergebnis, also ist CBuilder der "Böse" der nicht Rechnen kann.

    Ich weiss auch mittlerweile woran das liegt, wir holen die Variablen zum rechnen aus einer Datei und lesen diese per memcpy 4Byte ein. Beispielsweise speicherten wir 119.123456, so gibt es der VC++ auch zurück und rechnet damit und stimmt mit Calc.exe überein.

    Macht man das jetzt im CBuilder, bekommt man dort plötzlich 119.123456002569234 zurück. Der hängt einfach irgendwelchen Schmutz hinten dran. Das scheint er aber ständig zu machen und überall.

    @FrankBach
    Ich wollte jetzt mal das mit Integer in einem Beispiel in der Praxis testen.
    Ich verstehe es aber leider immernoch nicht ganz mit "/"
    Du sagst jeden Wert einfach *10000 nehmen... fein. Aber dann hast wieder 1.5 als Ergebnis. In deinem "Beispiel" hast einfach den ersten Wert nur *10000 genommen. Dann hast in diesem speziellen Fall natürlich "scheinbar" ein tolles Ergebnis aber was soll man bei 1.25/3.76 machen? Beide Werte *10000 bringt so nunja garnichts. Was man rauskürzen kann ist dann weg und muss man nicht extra anhängen.



  • peter-kun schrieb:

    Macht man das jetzt im CBuilder, bekommt man dort plötzlich 119.123456002569234 zurück.

    Joe_M. schrieb:

    Aber ich vermute, die Ursache liegt an der Ungenauigkeit von Fließkommazahlen. [...]
    Fließkommadatentypen verwendet man zum schätzen, Integerdatentypen zum rechnen.


Anmelden zum Antworten