Was ist die Verwendung des Suffixes `f` für den Float-Wert?

75

Ich frage mich, was der Unterschied zwischen diesen beiden Variablen in C ist:

float price = 3.00;

und

float price = 3.00f;

Was ist die Verwendung von Suffix fin diesem Fall?

Alex
quelle
1
Viele Duplikate, zB "f" nach number / float in Objective-C / C
Paul R
Ich kann das Gleitkomma-Quiz als weitere Lektüre empfehlen .
Martin Scharrer

Antworten:

73

3.00wird als a interpretiert double, im Gegensatz dazu 3.00fwird dies vom Compiler als a angesehen float.

Das fSuffix teilt dem Compiler einfach mit, welches a floatund welches a ist double.

Siehe MSDN (C ++)

James
quelle
1
Im Beispiel von OP sind die beiden Anweisungen also äquivalent, weil das Double sowieso automatisch in einen Float abgeschnitten wird.
Lincoln Bergeson
6
@ LincolnBergeson: Im OP-Fall ja. Wenn Sie jedoch eine Gleichung float price = 7.50 / 2.50;gegenüber haben, kann float price = 7.50f / 2.50f;das Ergebnis aufgrund der unterschiedlichen Auflösung abweichen. Im ersten Fall muss der Compiler die Berechnung durchführen und doubledann das Ergebnis in konvertieren float. Im zweiten Fall erfolgt die Berechnung in float. Beachten Sie, dass wenn nur ein Wert ist, doubledas Ganze als berechnet wird double. Der C-Compiler darf dies nicht optimieren, da sich die Rundung unterscheiden würde. Also floatvarA = floatvarB / 2.0schlechter abschneidet als mit 2.0f.
Martin Scharrer
36

Zusätzlich zu dem, was bereits gesagt wurde, ist es wichtiger, den Überblick über 1.0 gegenüber 1.0f zu behalten, als viele Menschen erkennen. Wenn Sie Code wie folgt schreiben:

float x;
...
float y = x * 2.0;

Dann wird x zu einem Double befördert, da 2.0 ein Double ist. Der Compiler darf diese Heraufstufung nicht optimieren, da dies sonst gegen den C-Standard verstoßen würde. Die Berechnung erfolgt mit doppelter Genauigkeit, und das Ergebnis wird implizit in einen Float abgeschnitten. Dies bedeutet, dass die Berechnung langsamer (wenn auch genauer) ist als wenn Sie 2.0f oder 2 geschrieben hätten.

Wenn Sie 2 geschrieben hätten, wäre die Konstante vom Typ int, der zu einem Float heraufgestuft würde, und die Berechnung wäre mit "Float-Präzision" durchgeführt worden. Ein guter Compiler würde Sie vor dieser Aktion warnen.

Lesen Sie hier mehr über die Regeln für die "übliche arithmetische Konvertierung":

http://msdn.microsoft.com/en-us/library/3t4w2bkb%28v=vs.80%29.aspx

Lundin
quelle
3
Tatsächlich generiert ein Compiler, der sein Geld wert ist, eine Multiplikation mit einfacher Genauigkeit für Ihr Beispiel float y = x * 2.0;. Tatsächlich generiert ein Compiler, der sein Geld wert ist, eine Multiplikation mit einfacher Genauigkeit float y = x * (double)0.1f;, eine viel beeindruckendere Leistung (aber immer noch eine korrekte Optimierung).
Pascal Cuoq
@PascalCuoq: Ein solcher Compiler würde den C-Standard verletzen. Sie weisen es ausdrücklich an, eine doubleMultiplikation mit 2.0und nicht durchzuführen 2.0f. Compiler dürfen keine Optimierung verwenden, die das numerische Ergebnis ändern würde.
Martin Scharrer
1
@MartinScharrer Es ändert nichts am numerischen Ergebnis (glauben Sie mir, ich habe das Gleitkomma-Goldabzeichen). Ich könnte auch darauf hinweisen, dass Clang diese Optimierung anwendet, aber es gibt so viel an Clang'c Gleitkomma, das nicht dem Standard entspricht, dass dies nichts beweisen würde.
Pascal Cuoq
2
@MartinScharrer Die nicht an die Behörde appellierende Referenz wurde von Figueroa geschrieben und enthält die Wörter "Doppelrundung harmlos" im Titel, aber ich kann sie in einer Version nicht finden, die sich derzeit nicht hinter einer Paywall befindet. Es zeigt, dass (float)((double)float_x * (double)float_y) == float_x * float_yeine Gleichheit, die der Compiler für diese Optimierung umgekehrt anwendet. Dies funktioniert, weil die Näherungen von 2 als doubleund floatidentisch sind.
Pascal Cuoq
16

Denn durch nicht angehängte Gleitkomma-Literale werden Doppelte verwendet, und Rundung bedeutet, dass selbst kleine Literale unterschiedliche Werte annehmen können, wenn sie auf Gleitkomma- und Doppelrundungen gerundet werden. Dies kann im folgenden Beispiel beobachtet werden:

float f=0.67;
if(f == 0.67) 
  printf("yes");
else 
  printf("no");  

Dies wird ausgegeben no, da 0.67es einen anderen Wert hat, wenn es auf Float gerundet wird, als wenn es auf Double gerundet wird. Auf der anderen Seite:

float f=0.67;
if(f == 0.67f) 
  printf("yes");
else 
  printf("no"); 

Ausgänge yes.

Das Suffix kann entweder in Groß- oder Kleinbuchstaben angegeben werden.

Versuchen Sie dies auch:

printf(" %u %u\n", sizeof(.67f), sizeof(.67));

Überprüfen Sie @ Codepade

Grijesh Chauhan
quelle
Das Vergleichen von Gleitkommazahlen mit == ist eine schlechte Praxis. Grund dafür sind die Fehler, die sich bei der Konvertierung von Dezimal in Binär ergeben. Diese Fehler häufen sich, wenn Sie mit der Bearbeitung von Gleitkommazahlen beginnen, sodass kein genauer Vergleich möglich ist. Aus diesem Grund sollten Sie niemals erwarten, dass eine schwebende Zahl genau ist.
Ignas2526
@ Ignas2526 dann was würdest du vorschlagen, wenn ich irgendwann eintrete, um Floats zu vergleichen. Können Sie mir einen Hinweis geben, wo Sie weiterlesen können?
Grijesh Chauhan
2
Hier sind einige Seiten, die sich mit dem hier erwähnten Problem
befassen
@ Ignas2526 danke Ich werde es lesen, wenn ich etwas finde, das ich in meiner Antwort hinzufügen kann, werde ich es aktualisieren. Ihr Link wird auch für andere hilfreich sein.
Grijesh Chauhan
6

3.00 ist ein Double, 3.00f ist ein Float.

Erik
quelle
0

Dies liegt daran, dass der Standardtyp eines numerischen Gleitkomma-Literals - die Zeichen 3.00 sind doppelt und nicht float. Um dies zu kompilieren, müssen Sie das Suffix f (oder F) hinzufügen.

entspannen
quelle
0

Hinzufügen einiger weiterer Kombinationen von Vergleichen zwischen Float- und Double-Datentypen.

int main()
{
    // Double type constant(3.14) converts to Float type by 
    // truncating it's bits representation 
    float a = 3.14; 
    // Problem: float type 'a' promotes to double type and the value 
    // of 'a'  depends on how many bits added to represent it.
    if(a == 3.14)   
        std::cout<<"a: Equal"<<std::endl;
    else
        std::cout<<"a: Not Equal"<<std::endl; 

    float b = 3.14f; // No type conversion
    if(b == 3.14)    // Problem: Float to Double conversion
        std::cout<<"b: Equal"<<std::endl;
    else
        std::cout<<"b: Not Equal"<<std::endl;

    float c = 3.14; // Double to Float conversion (OK even though is not a good practice )
    if(c == 3.14f)  // No type conversion 
        std::cout<<"c: Equal"<<std::endl;  // OK
    else
        std::cout<<"c: Not Equal"<<std::endl;

    float d = 3.14f;
    if(d == 3.14f)
        std::cout<<"d: Equal"<<std::endl; // OK
    else
        std::cout<<"d: Not Equal"<<std::endl;

    return 0;
}    

Ausgabe:

 a: Not Equal
 b: Not Equal
 c: Equal
 d: Equal
SridharKritha
quelle
-1

Oft ist der Unterschied nicht wichtig, da der Compiler die Doppelkonstante ohnehin in einen Float umwandelt. Beachten Sie jedoch Folgendes:

template<class T> T min(T a, T b)
{
  return (a < b) ? a : b;
}

float x = min(3.0f, 2.0f); // will compile
x = min(3.0f, 2);   // compiler cannot deduce T type
x = min(3.0f, 2.0); // compiler cannot deduce T type
Frederik Slijkerman
quelle
1
Ihre Antwort erklärt den Unterschied zwischen 3.00 und 3.00f nicht klar ...
James
1
Genau ... Sie können einige Informationen hinzufügen, aber Sie beantworten die Frage nicht ...
James
1
Wenn Sie versuchen, eine Doppelkonstante in einem Float zu speichern, erhalten Sie eine implizite Verschlechterung von Double zu Float. Bei Ausdrücken kann der Compiler jedoch keine Doppelkonstanten in float konvertieren, ohne den C / C ++ - Standard zu verletzen. Wenn eine Doppelkonstante im selben Ausdruck wie ein Float steht, verlangen die Regeln der "üblichen arithmetischen Konvertierung" von C / C ++, dass der Float implizit zu einem Double heraufgestuft wird.
Lundin
4
Warum antworten Sie auch mit C ++, wenn das OP in C schreibt? Ihr Beispiel ist in C irrelevant, da C nicht die gleiche strenge Typprüfung wie C ++ hat.
Lundin