"F" nach Nummer

102

Was bedeutet das fnach den Zahlen? Ist das von C oder Objective-C? Gibt es einen Unterschied, wenn dies nicht zu einer konstanten Zahl hinzugefügt wird?

CGRect frame = CGRectMake(0.0f, 0.0f, 320.0f, 50.0f);

Können Sie erklären, warum ich nicht einfach schreiben würde:

CGRect frame = CGRectMake(0, 0, 320, 50);
typoneerror
quelle

Antworten:

88
CGRect frame = CGRectMake(0.0f, 0.0f, 320.0f, 50.0f);

verwendet Float-Konstanten. (Die Konstante 0.0 deklariert normalerweise ein Double in Objective-C; wenn Sie ein f am Ende setzen - 0.0f - deklariert die Konstante als (32-Bit) float.)

CGRect frame = CGRectMake(0, 0, 320, 50);

verwendet Ints, die automatisch in Floats konvertiert werden.

In diesem Fall gibt es keinen (praktischen) Unterschied zwischen den beiden.

Frank Shearar
quelle
24
Theoretisch ist der Compiler möglicherweise nicht intelligent genug, um sie zur Kompilierungszeit in Float zu konvertieren, und würde die Ausführung mit vier Int-> Float-Konvertierungen (die zu den langsamsten Casts gehören) verlangsamen. Obwohl dies in diesem Fall fast unwichtig ist, ist es immer besser, f bei Bedarf korrekt anzugeben: In einem Ausdruck kann eine Konstante ohne den richtigen Bezeichner die Umwandlung des gesamten Ausdrucks in double erzwingen, und wenn er sich in einer engen Schleife befindet, kann dies zu Leistungseinbußen führen bemerkbar.
Matteo Italia
60

Überprüfen Sie im Zweifelsfall die Assembler-Ausgabe. Schreiben Sie zum Beispiel ein kleines, minimales Snippet wie dieses

#import <Cocoa/Cocoa.h>

void test() {
  CGRect r = CGRectMake(0.0f, 0.0f, 320.0f, 50.0f);
  NSLog(@"%f", r.size.width);
}

Kompilieren Sie es dann mit der -SOption zum Assembler .

gcc -S test.m

Speichern Sie die Assembler-Ausgabe in der test.sDatei, entfernen Sie sie .0faus den Konstanten und wiederholen Sie den Kompilierungsbefehl. Dann machen Sie eine diffder neuen test.sund vorherigen. Denken Sie, das sollte zeigen, ob es echte Unterschiede gibt. Ich denke, zu viele haben eine Vorstellung davon, was der Compiler ihrer Meinung nach tut, aber am Ende des Tages sollte man wissen, wie man Theorien überprüft.

Epatel
quelle
11
Die Ausgabe stellte sich für mich als identisch heraus, auch ohne -O. Ich bin auf i686-apple-darwin10-gcc-4.2.1 (GCC)
kizzx2
2
Ich habe das obige Beispiel mit LLVM Version 7.0.0 (clang-700.0.65) x86_64-apple-darwin15.0.0 ausprobiert und die .out-Dateien waren ebenfalls identisch.
Nick
43

Manchmal gibt es einen Unterschied.

float f = 0.3; /* OK, throw away bits to convert 0.3 from double to float */
assert ( f == 0.3 ); /* not OK, f is converted from float to double
   and the value of 0.3 depends on how many bits you use to represent it. */
assert ( f == 0.3f ); /* OK, comparing two floats, although == is finicky. */
Kartoffelklatsche
quelle
26

Es teilt dem Computer mit, dass dies eine Gleitkommazahl ist (ich nehme an, Sie sprechen hier von c / c ++). Wenn nach der Zahl kein f steht, wird es als Doppel oder Ganzzahl betrachtet (je nachdem, ob es eine Dezimalstelle gibt oder nicht).

3.0f -> float
3.0 -> double
3 -> integer
NickLH
quelle
Ist diese Konvention Teil des C ++ - Standards oder befindet sie sich im Compiler?
Jxramos
1
Soweit ich das beurteilen kann, gehört es zum Standard (jemand korrigiert mich, wenn ich falsch liege). Die schnellste Referenz, die ich finden konnte, ist open-std.org/jtc1/sc22/open/n2356/lex.html#lex.fcon , aber es gibt wahrscheinlich aktuellere Referenzen, wenn Sie danach suchen möchten .
NickLH
5

Ein Gleitkomma-Literal in Ihrem Quellcode wird als Double analysiert. Das Zuweisen zu einer Variablen vom Typ float verliert an Genauigkeit. Mit viel Präzision werfen Sie 7 signifikante Ziffern weg. Mit dem Postfix "f" können Sie dem Compiler sagen: "Ich weiß, was ich tue, das ist beabsichtigt. Ärgern Sie mich nicht darüber."

Die Wahrscheinlichkeit, einen Fehler zu produzieren, ist übrigens nicht so gering. Viele Programme sind auf einen schlecht durchdachten Gleitkomma-Vergleich oder die Annahme gestoßen, dass 0,1 genau darstellbar ist.

Hans Passant
quelle
4

Das f, von dem Sie sprechen, soll dem Compiler wahrscheinlich mitteilen, dass es mit einem Float arbeitet. Wenn Sie das weglassen f, wird es normalerweise in ein Doppel übersetzt.

Beide sind Gleitkommazahlen, aber a floatverwendet weniger Bits (also kleiner und weniger genau) als a double.

Yuri
quelle
3

Es ist eine C-Sache - Gleitkomma-Literale haben standardmäßig die doppelte Genauigkeit (doppelt). Durch Hinzufügen eines f-Suffixes erhalten sie eine einfache Genauigkeit (float).

Sie können Ints verwenden, um die Werte hier anzugeben, und in diesem Fall macht es keinen Unterschied, aber die Verwendung des richtigen Typs ist eine gute Angewohnheit - Konsistenz ist im Allgemeinen eine gute Sache, und wenn Sie diese Werte später ändern müssen, können Sie dies tun Ich werde auf den ersten Blick wissen, um welchen Typ es sich handelt.

Paul R.
quelle
2

Von C. Es bedeutet Float-Literal-Konstante. Sie können sowohl "f" als auch ".0" weglassen und in Ihrem Beispiel Ints verwenden, da Ints implizit in Floats konvertiert werden.

Wilde Katze
quelle
1

Es ist mit ziemlicher Sicherheit von C und spiegelt den Wunsch wider, einen "Float" anstelle eines "Double" -Typs zu verwenden. Es ähnelt Suffixen wie L auf Zahlen, um anzuzeigen, dass es sich um lange Ganzzahlen handelt. Sie können nur Ganzzahlen verwenden, und der Compiler konvertiert entsprechend automatisch (für dieses spezielle Szenario).

Tyranid
quelle
0

Normalerweise teilt es dem Compiler mit, dass der Wert a ist float, dh eine Gleitkomma-Ganzzahl. Dies bedeutet , dass sie speichern können ganze Zahlen, Dezimalzahlen und Exponenten, zum Beispiel 1, 0.4oder 1.2e+22.

Polynom
quelle