16

Oft muss ich CGFloat zu einer int Boden oder Decke, für die Berechnung eines Array-Index.Wie kann man einen CGFloat sicher in den Boden stellen?

Das Problem, das ich permanent mit floorf(theCGFloat) oder ceilf(theCGFloat) sehe, ist, dass es Probleme mit Gleitkomma-Ungenauigkeiten geben kann.

Also was ist, wenn meine CGFloat ist 2.0f aber intern wird es als 1.999999999999f oder so ähnlich dargestellt. Ich mache floorf und bekomme 1.0f, was wiederum ein Float ist. Und dennoch muss ich dieses Biest ins int werfen, was ein anderes Problem hervorbringen kann.

Gibt es eine bewährte Methode, wie Boden oder ceil einen float zu einem int, dass so etwas wie 2.0 würde versehentlich niemals würde 1 und so etwas wie 2.0 platt bekommt nie versehentlich 2 erhalten ceiled?

+4

Diese Frage nicht richtig beantwortet werden kann, bis Spezifikationen zur Verfügung gestellt werden, um den Fehler in dem Eingangswert zu beschreiben und was die Folgen sind Werte der Rücksendung, die zu sind hoch oder zu niedrig. Es gibt Kompromisse zwischen der Rückgabe eines zu hohen Werts, weil der vorherige Rundungsfehler den Wert zu hoch gemacht hat, und einem zu niedrigen Wert, da der Wert künstlich angepasst wurde, um den vorhergehenden Fehler zu kompensieren, und umgekehrt. Ohne Erklärung des Zusammenhangs gibt es keine einzige richtige Antwort. –

Antwort

19

Es gibt ein paar Missverständnisse in Ihrer Frage.

was, wenn mein CGFloat 2.0f ist aber intern ist dargestellt, wie 1.999999999999f

nicht passieren kann; 2.0, wie alle vernünftig kleinen ganzen Zahlen, hat eine exakte Darstellung in Fließkommazahl. Wenn Ihr CGFloat2.0f ist, dann ist es wirklich 2.0.

so etwas wie 2.0 würde nie versehentlich 2

Die Decke von 2,0 ist 2 ceiled erhalten; Was könnte es sonst sein?


Ich denke, die Frage, die Sie wirklich fragen, ist „nehme ich eine Berechnung zu tun, die ein ungenaues Ergebnis erzeugt, die mathematisch exakt 2,0 sein sollte, aber tatsächlich etwas weniger ist, wenn ich mich bewerben floor zu diesen Wert bekomme ich 1.0 statt 2.0 - wie verhindere ich das?"

Das ist eigentlich eine recht subtile Frage, die keine einzige hat‚richtige‘Antwort. Wie haben berechnet Sie den Eingabewert? Was Sie mit dem Ergebnis zu tun?

1

EDIT - die Kommentare aus Gründen lesen, warum diese Antwort nicht richtig :)

Casting ein float auf eine int eine implizite floorf ist das heißt (int)5.95 ist. Wenn es Ihnen nichts ausmacht, dann einfach casten :)

Wenn Sie aufrunden möchten, dann werfen Sie einfach das Ergebnis einer ceilf - Casting nach der Rundung sollte überhaupt keine Fehler einführen (oder, wenn Sie wollen, fügen Sie hinzu eine vor dem Casting, dh `(int) (5.9 + 1) 'ist' 6 '- das gleiche wie das Aufrunden.

zur nächsten runden, fügen Sie einfach 0,5-(int)(5.9+0.5) ist 6 aber (int)(5.4+0.5)5 ist. Obwohl ich einfach roundf(5.9) verwenden würde :)

+8

Casting float zu int ist kein impliziter floor. Es ist, in C und einigen anderen gebräuchlichen Sprachen, eine Kürzung (gegen Null). Floor rundet auf die nächste ganze Zahl in der Richtung der negativen Unendlichkeit. Konvertieren von -3.5 in ganzzahlige Ausbeuten -3, aber Boden (-3.5) ist -4. –

+0

OK, das ist ein guter Punkt - ich würde zu sehr vereinfacht, bis ich falsch verstanden habe :) – deanWombourne

18

Swift ergänzende Antwort

ich füge dies als ergänzende Antwort für diejenigen, die hier auf der Suche kommen, wie floor und ceil mit einem CGFloat verwenden (wie ich).

var myCGFloat: CGFloat = 3.001 
floor(myCGFloat) // 3.0 
ceil(myCGFloat) // 4.0 

Und wenn ein Int benötigt wird, dann kann es zu einem umgewandelt werden.

var myCGFloat: CGFloat = 3.001 
Int(floor(myCGFloat)) // 3 
Int(ceil(myCGFloat)) // 4 

aktualisieren

Es besteht keine Notwendigkeit mehr, die C floor und ceil Funktionen zu nutzen. Sie können den Swift round() mit rounding rules verwenden.

var myCGFloat: CGFloat = 3.001 
myCGFloat.round(.down) // 3.0 
myCGFloat.round(.up) // 4.0 

Wenn Sie die ursprünglichen Variablen nicht ändern wollen, dann rounded() verwenden.

Hinweise

  • Arbeiten mit 32- und 64-Bit-Architekturen.

Siehe auch