Ich habe eine einfache Routine, die das Seitenverhältnis aus einem Fließkommawert berechnet. Für den Wert 1.77777779 gibt die Routine die Zeichenfolge "16: 9" zurück. Ich habe das auf meiner Maschine getestet und es funktioniert gut.
Die Routine wird wie folgt angegeben:
%Vor%Jetzt auf einer anderen Maschine bekomme ich völlig andere Ergebnisse. Also auf meiner Maschine gibt 1.77777779 "16: 9", aber auf einer anderen Maschine bekomme ich "38:21".
Hier ist ein interessantes Teil der C # -Spezifikation aus Abschnitt 4.1.6:
Gleitkommaoperationen können sein mit höherer Präzision ausgeführt als der Ergebnistyp der Operation Zum B. einige Hardware-Architekturen Unterstütze ein "erweitertes" oder "langes Doppel" Fließkommatyp mit größerer Reichweite und Präzision als der doppelte Typ, und implizit alle durchführen Fließkommaoperationen, die dies verwenden höherer Präzisionstyp. Nur bei Übermäßige Kosten in der Leistung können z Hardware-Architekturen gemacht werden Gleitkommaoperationen mit durchführen weniger Präzision, und nicht erfordern eine Implementierung zu verfallen sowohl Leistung als auch Präzision, C # erlaubt eine höhere Präzision zu sein Wird für alle Fließkommazahlen verwendet Operationen. Anders als mehr zu liefern präzise Ergebnisse, das hat selten was messbare Effekte.
Es ist möglich, dass dies einer der "messbaren Effekte" ist, dank diesem Aufruf an Ceiling. Nimmt man die Obergrenze einer Gleitkommazahl, wie andere angemerkt haben, vergrößert sich eine Differenz von 0,000000002 um neun Größenordnungen, weil aus 15,99999999 in 16 und 16,00000001 in 17 wird. Zwei Zahlen, die vor der Operation geringfügig abweichen, unterscheiden sich danach massiv; Der kleine Unterschied könnte auf die Tatsache zurückzuführen sein, dass verschiedene Maschinen mehr oder weniger "Extra-Präzision" in ihren Fließkommaoperationen haben können.
Einige verwandte Probleme:
Um Ihr spezifisches Problem zu lösen, wie man ein Seitenverhältnis aus einem Float berechnen kann: Ich würde das möglicherweise auf eine völlig andere Art und Weise lösen. Ich würde einen Tisch so machen:
%Vor%und jetzt ist Ihre Implementierung
%Vor%Beachten Sie, dass sich der Code nun ähnlich wie die Operation verhält, die Sie ausführen möchten: Wählen Sie aus dieser Liste mit den üblichen Ratios diejenige aus, bei der die Differenz zwischen dem angegebenen Verhältnis und dem gemeinsamen Verhältnis minimiert ist.
Ich würde keine Fließkommazahlen verwenden, wenn ich nicht wirklich müsste. Sie sind aufgrund von Rundungsfehlern zu anfällig für solche Dinge.
Können Sie den Code in doppelter Genauigkeit ändern? (Dezimal wäre Overkill). Wenn Sie dies tun, gibt es konsistentere Ergebnisse?
Warum unterscheiden sich die verschiedenen Maschinen voneinander? Was sind die Unterschiede zwischen den beiden Maschinen?
So etwas wie könnte die Ursache sein.
Versuchen Sie Math.Round
anstelle von Math.Ceiling
. Wenn Sie mit 16.0000001 enden und aufrunden, werden Sie diese Antwort falsch verwerfen.
Verschiedene andere Vorschläge:
(double) 0.1
cast ist unnötig. carryon
ablegen. Überarbeitet (ungetestet):
%Vor% Wenn der Index 9 ist, erwarten Sie etwas wie upper = 16.0000001 oder upper = 15.9999999. Welche Sie erhalten, hängt vom Rundungsfehler ab, der auf verschiedenen Maschinen unterschiedlich sein kann. Wenn es 15.999999 ist, ist roundedUpValue - upper <= 0.1
wahr und die Schleife endet. Wenn es 16.0000001 ist, ist roundedUpValue - upper <= 0.1
falsch und die Schleife läuft weiter, bis Sie index > 20
erreichen.
Stattdessen sollten Sie vielleicht versuchen, auf die nächste ganze Zahl zu runden und zu überprüfen, ob der absolute Wert der Differenz von dieser ganzen Zahl klein ist. In anderen Worten, verwenden Sie etwas wie if (Math.Abs(Math.Round(upper) - upper) <= (double)0.0001 || index > 20)
Tags und Links c#