Modulo falsch Berechnung?
-
@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.
-
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ß Bilder pro Sekunde, bzw. Sekunden pro Bild. Für 7191.04794 Frames (falls das hier überhaupt berechnet werden soll (?)) wären das dann 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 (bzw. ), 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ürd
(alsoframes
, 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) abgerundettime_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
undShowMessage
), 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/msDafü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.
-
@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 1ms). mit diesen
double
kann der Fehler jetzt abhängig von (großem)frames
nahezu beliebig groß werden.
-
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.
-
@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.
-
@noLust naja ich weiß nicht nicht wie ich sagen soll aber ich bin nicht wie ihr, ich hab mit dem allem was sich da als Menschen bezeichnen nix gemeinsames, und das ist auch gut so.
-
int64_t time_in_milliseconds = (int64_t) round((1001.0 / 24000.0 * 47.952 * 1000)); //muss sein 2000 if(time_in_milliseconds == 2000) cout << "it's true" <<endl;