Modulo falsch Berechnung?



  • Um die Probleme zu umgehen geht auch folgendes, einfach die Werte bisschen erhöhen dann klappts auch ohne Werte dazu addieren, runden oder sonstiges.

    	double A = 90000.024*10;
    	double B = 0.025*10;
    	double C = (A/B);
    	int R = static_cast<int>(C)%1000; //0
    
    	cout << R <<endl;
    
    	A = 90000.025*10;
    	B = 0.025*10;
    	C = (A/B);  //3600001
    	R = static_cast<int>(C)%1000;   //1
    
    	cout << R <<endl;
    
    	if(C==3600001)
    		cout << "true"  <<endl;
    

    is schon spät muss erstmal pennen

    Update: ist Schrott funktioniert nicht zuverlässig.



  • @Gestalt sagte in Modulo falsch Berechnung?:

    double B = 0.025*10;

    Naja, 0.25 kann exakt in double oder float dargestellt werden, 0.025 aber nicht. 0.24 übrigens nicht. Deine Berechnung funktioniert also nur "zufällig", du solltest bei Fließkommazahlen IMMER mit Rundungsfehlern/Darstellungsproblemen rechnen.

    Dein erster Fall funktioniert, weil 3600000.96 (bzw. ...959999... in double) rauskommt, was sowieso in der 2. Nachkommastelle klein ist, d.h. 0.96 ist weit genug von der 1 entfernt, sodass du kein Problem hast.

    Der 2. Fall ist spannender. Er funktioniert, weil 0.25 exakt ist.

    Mit nicht exakt darstellbaren Nachkommazahlen, die mathematisch gesehen aber in deiner Rechnung eine ganze Zahl ergeben, wirst du Probleme haben, weil das Ergebnis dann auch geringfügig größer (kein Problem für dich) oder kleiner (da hast du dann ein Problem) als die ganze Zahl sein kann.



  • @wob sagte in Modulo falsch Berechnung?:

    stellungsproblemen rec

    habe zur Not noch Deine Variante die ja noch im Code steht, ich probiere das aber später nochmal durch bis es kracht :). Nur im Moment bastel ich an anderen Dingen, die mich 4 Stunden ehr ausm Bett geholt haben als eigentlich geplant.

    Update: es bleibt dabei "std::floor(a + 0.00001);" beste Variante.


  • Gesperrt

    Tipp: Wenn es float, double, usw. sein soll ... und die Ergebnisse genau sein sollen ... dann immer die C++-Boost-Library verwenden. Die Jungs machen quasi nix anderes.

    Und hier https://en.wikipedia.org/wiki/Accuracy_and_precision und hier https://en.wikipedia.org/wiki/Propagation_of_uncertainty steht mehr darüber.

    Edit: Eigentlich wollte ich das in die Signatur schreiben, aber das darf ich nicht:

    Menschen machen Fehler, aber Computer machen noch mehr Fehler. 😉



  • @hustbaer sagte in Modulo falsch Berechnung?:

    @Gestalt sagte in Modulo falsch Berechnung?:

    7191.04794

    Ich check grad nicht was du erreichen willst. Willst du ausrechnen wie lange 7191.04794 Frames eines NTSC Videos brauchen? Und von der Zeit dann sozusagen den Nachkommaanteil in Millisekunden? Verstehe nicht wozu das gut sein soll.

    Das würde mich auch interessieren. Ich habe das Gefühl, dass man hier möglicherweise schon früher einen anderen Ansatz wählen kann, um Rundungsfehler zu minimieren. Soweit ich weiß sind diese PAL/NTSC Frameraten und Frequenzen auch alles Rationale Zahlen, da könnte man sogar weitgehend auf Fließkomma-Berechnungen verzichten, wenn man es wirklich exakt haben will - bzw. erst ganz am Ende das Ergebnis nach double umrechnen. So akkumulieren sich die Fehler in den Rechenschritten dann auch nicht auf.

    NTSC macht so weit ich weiß 300001001=29.970029{30000 \over 1001} = 29.\overline{970029} Bilder pro Sekunde, bzw. 100130000=0.03336{1001 \over 30000} = 0.0333\overline{6} Sekunden pro Bild. Für 7191.04794 Frames (falls das hier überhaupt berechnet werden soll (?)) wären das dann 719104794100000100130000=7198238987943000000000=239.941299598{719104794 \over 100000} \cdot {1001 \over 30000} = {719823898794 \over 3000000000} = 239.941299598 Sekunden (exakt!).

    Das nur als Beispiel, wie man Berechnungen wie diese mit Integer-Arithmetik in Zähler und Nenner machen und erst ganz am Schluss nach Fließkomma konvertieren könnte. Ich würde vermuten, dass sich damit einige Rundungs-Scherereien vermeiden ließen. Wäre trotzdem gut zu wissen, was du überhaupt berechnen willst @Gestalt - vielleicht ist das ja ein XY-Problem (?).



  • @Finnegan sagte in Modulo falsch Berechnung?:

    7191.04794

    ja für mich ist es sinnvoll sonst würde ich es nicht machen und Zeit in ein Programm stecken. In Deiner Berechnung nutzt Du das falsche Format für den Wert "7191.04794", diesem Wert liegt NTSC-FILM 23,97fps zugrunde und nicht 29,97fps. Diese "7191.04794" sind genau und zwar exakt nocht exakter geht es nicht 05 Stunden 00 Minuten 00 sekunden und 002 Millisekunden. Mein Programm funktioniert ich habe auch keine Rundungsfehler auch nicht bei 999 Stunden 59 Minuten 59 Sekunden 999Millisekunden das sind Exakt und ganz genau 86291999.97603 Frames im 23,97 NTSC FILM Format. Ich finde das nicht gut das man nach dem Sinn gefragt wird nur weil ich Dinge mache die eine anderer nicht macht und er deshalb darin keinen Sinn sieht.



  • Trotzdem benutzt man dafür dann aber keine Fließkommazahlen!



  • @Th69 Ok, dann Beweise mir das in dem Du "5006398.17" im NTSC 23,97 umrechnest zu Stunden/Minuten/Sekunden/Millisekunden ohne Fließkomma-Datentypen zu benutzen. Das Ergebniss reicht vorerst aus.



  • So, wie schon @Finnegan geschrieben hat, mit rationalen Zahlen.
    Laut NTSC-Film entspricht dies 24/1.00124 / 1.001 (bzw. 24000/100124000 / 1001), d.h.

    const int64_t ms_per_s = 1000;
    int64_t time_in_milliseconds = frames * ms_per_s * 1001 / 24000;
    

    frames sollte dabei aber auch schon eine rationale Zahl sein (bzw. in so eine umgewandelt werden können) - darum hatte ich dich ja auch schon gefragt woher der Wert für d (also frames, wie wir jetzt wissen) kommt?
    Du könntest dafür z.B. die Boost-Library Rational Numbers benutzen.

    Für frames = 5006398.17 (bzw. frames = Rational(500639817, 100)) sollte (wenn der Windows-Rechner sich nicht verrechnet hat) abgerundet time_in_milliseconds = 208808523 (bzw. 58h 0m 8s 523ms herauskommen).



  • @Th69 sagte in Modulo falsch Berechnung?:

    int64_t

    ja das Problem ist auch noch das es im NTSC-FILM 2 verschiedene Formate gibt einmal 24.0fps und einmal 23,976fps - das muss erstmal unterschieden werden. Deshalb ist alles ersteinmal hinfällig was dieses Format betrifft. Das heißt 23,97 ist schon falsch von dem ich ausgegangen bin. Dein Beispiel ist gut ich guck mir das mal genauer an. Aber ich werde sehr wahrscheinlich mit diesem 23,976fps und nicht mit (24000/1001) und dann zusätzlich halt 24.00fps was ja einfach ist arbeiten.

    So hab erstmal auf 23,976 umgeschrieben, selber hatte ich damit nie zu tun nur eben mit PAL-Zeiten deshalb kann ich es nicht überprüfen. Herauskommen sollte beim Ergebniss eigentlich 58:01:01:000 - wenn 23,976fps zugrunde liegen. Der Frame-Wert dafür liegt bei 5007651.336.

    NTSC 29,97 / NTSC FILM 23,976 = 1.25.
    6259564.17/ 5007651.336 = 1.25. (TimeCode 58:01:01:000)

    Update: Habe mir mal Deine Berechnung reingezogen, irgendwas stimmt da nicht.
    Komme damit nicht klar die Ergebnisse sind komplett daneben.



  • Da du anscheinend das RAD Studio (AnsiString und ShowMessage), also den Embarcadero-Compiler, benutzt, könntest du auch den Datentyp System.Currency verwenden - dieser hat exakt 4 Nachkommastellen (ist dem Namen nach eigentlich für Währungen gedacht, aber auch für andere Anwendungsfälle, wie deinem, geeignet).



  • @Th69 also bei NTSC 23.976 benötige ich maximal 6 Nachkommastellen.
    86313599.976024 = 999:59:59:999 h/m/s/ms

    Dafür reicht dann aber int nicht mehr aus.



  • Ich schrieb ja auch int64_t.

    Und für Fixpoint-Arithmetics habe ich auch noch Compositional Numeric Library (CNL) gefunden (dort kannst du dann die Anzahl der max. Nachkommastellen explizit angeben).

    Auch wenn ich nicht verstehe, warum du bei Millisekunden-Genauigkeit mehr als 3 Nachkommastellen benötigst.



  • @Th69 Es geht auch mit 3 nur muss ich dann aufrunden.


  • Gesperrt

    @Th69 sagte in Modulo falsch Berechnung?:

    int64_t time_in_milliseconds = frames * ms_per_s * 1001 / 24000;

    Es ist besser, das ein wenig umzustellen:

    int64_t time_in_milliseconds = (int64_t) (1001.0 / 24000.0 * frames * ms_per_s);

    wobei es auch hierbei Ungenauigkeiten gibt: * und sogar / sind in diesem Fall Ungenauigkeitsbehaftet.



  • @Gestalt sagte in Modulo falsch Berechnung?:

    Ich finde das nicht gut das man nach dem Sinn gefragt wird nur weil ich Dinge mache die eine anderer nicht macht und er deshalb darin keinen Sinn sieht.

    Falls du es noch nicht mitbekommen haben solltest: Hier wird im Allgemeinen nicht nach dem "warum" gefragt, um jemanden auszulachen, sondern um besser helfen zu können.



  • @Finnegan sagte in Modulo falsch Berechnung?:

    ch dem "warum" ge

    Ich weiß wie Menschen sind, hatte mein ganzes leben lang Zeit sie zu analysieren mir brauch keiner was von alle sind so lieb erzählen. Es gibt Ausnahmen die sind aber wirklich selten.



  • @noLust sagte in Modulo falsch Berechnung?:

    @Th69 sagte in Modulo falsch Berechnung?:

    int64_t time_in_milliseconds = frames * ms_per_s * 1001 / 24000;

    Es ist besser, das ein wenig umzustellen:

    int64_t time_in_milliseconds = (int64_t) (1001.0 / 24000.0 * frames * ms_per_s);

    wobei es auch hierbei Ungenauigkeiten gibt: * und sogar / sind in diesem Fall Ungenauigkeitsbehaftet.

    Und was ist daran nun "besser"? Die Integer-Berechnung war immer auf volle, "abgelaufene" Millisekunden genau, egal wie viele Frames man hat (Fehler <\lt 1ms). mit diesen double kann der Fehler jetzt abhängig von (großem) frames nahezu beliebig groß werden.



  • @noLust

    int64_t time_in_milliseconds = (int64_t) (1001.0 / 24000.0 * 47.952 * 1000);  //muss sein 2000 ist aber 1999
    

    also so gehts nicht, weil das "47.952" 2sekunden bzw. 2000ms sind
    da bleib ich doch liebers bei meiner Variante.


  • Gesperrt

    @Finnegan Ich hab da auch noch ein round vergessen 😅

    @Gestalt sagte in Modulo falsch Berechnung?:

    Es gibt Ausnahmen die sind aber wirklich selten.

    Na ja, irgendwie kaufe ich dir die Unschuldslammnummer auch nicht so ganz ab. 😃


Anmelden zum Antworten