83

I am wondering what the difference is between these two variables in C:

float price = 3.00;

and

float price = 3.00f;

What is the use of suffix f in this case?

Murphy
  • 3,827
  • 4
  • 21
  • 35
Alex
  • 937
  • 1
  • 7
  • 7
  • 1
    Many duplicates, e.g. ["f" after number/float in Objective-C/C](http://stackoverflow.com/questions/2391818/f-after-number-float-in-objective-c-c) – Paul R Feb 17 '11 at 08:40
  • I can recommend the [Floating point quiz](http://blog.frama-c.com/index.php?post/2011/11/08/Floating-point-quiz) as further reading. – Martin Scharrer Apr 11 '17 at 11:17
  • The `f` _sometimes_ makes a [value difference](https://stackoverflow.com/q/66631288/2410359) in assignment. – chux - Reinstate Monica Sep 19 '21 at 08:56

7 Answers7

89

3.00 is interpreted as a double, as opposed to 3.00f which is seen by the compiler as a float.

The f suffix simply tells the compiler which is a float and which is a double.

See MSDN (C++)

James
  • 1,569
  • 10
  • 18
  • 1
    So in OP's example, the two statements are equivalent, because the double is automatically truncated into a float anyway? – Lincoln Bergeson Jan 25 '17 at 04:51
  • 7
    @LincolnBergeson: In the OP case yes. However if you would have an equation `float price = 7.50 / 2.50;` versus `float price = 7.50f / 2.50f;` then the result might differ due to different resolution. In the first case the compiler will have to do the calculation as `double` then convert the result to `float`. In the second case the calculation is done in `float`. Note that if only one value is `double` the whole thing is calculated as `double`. The C compiler is not allowed to optimize that away as they rounding would differ. So `floatvarA = floatvarB / 2.0` performs worse than with `2.0f`. – Martin Scharrer Apr 11 '17 at 10:14
37

In addition to what has already been said, keeping track of 1.0 versus 1.0f is more important than many people realize. If you write code like this:

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

Then x will be promoted to a double, because 2.0 is a double. The compiler is not allowed to optimize that promotion away or it would violate the C standard. The calculation takes place with double precision, and then the result is then implicitly truncated into a float. This means that the calculation will be slower (though more accurate) than it would have been if you had written 2.0f or 2.

Had you written 2, the constant would be of int type, which would be promoted to a float, and the calculation would have been done with "float precision". A good compiler would warn you about this promotion.

Read more about the "usual arithmetic conversion" rules here:

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

Lundin
  • 195,001
  • 40
  • 254
  • 396
  • 3
    Actually, a compiler worth its salt will generate a single-precision multiplication for your example `float y = x * 2.0;`. In fact, a compiler worth its salt will generate a single-precision multiplication for `float y = x * (double)0.1f;`, a much more impressive feat (but still a correct optimization). – Pascal Cuoq Jul 06 '13 at 16:54
  • @PascalCuoq: Such a compiler would violate the C standard. You _explicitly_ telling it to do a `double` multiplication by using `2.0` and not `2.0f`. Compilers are not allowed to use optimization which would change the numeric outcome. – Martin Scharrer Apr 11 '17 at 10:17
  • 1
    @MartinScharrer It doesn't change the numeric outcome (believe me, I have the floating-point gold badge). I could also point out that Clang applies this optimization, but there is so much about Clang'c floating-point that is non-standard that this would not prove anything. – Pascal Cuoq Apr 12 '17 at 06:24
  • 3
    @MartinScharrer The non-appealing-to-authority reference is written by Figueroa and contains the words “double rounding innocuous” in the title but I cannot find it in a version that's not behind a paywall right now. It shows that `(float)((double)float_x * (double)float_y) == float_x * float_y`, an equality that the compiler applies in reverse for this optimization. This works because the approximations of 2 as `double` and `float` are identical. – Pascal Cuoq Apr 12 '17 at 06:30
23

Because by unsuffixed floating-point literals are doubles, and rounding means that even small literals can take on different values when rounded to float and double. This can be observed in the following example:

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

This will output no, because 0.67 has a different value when rounded to float than it does when rounded to double. On the other hand:

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

outputs yes.

The suffix can be specified using either upper or lowercase letters.

Try this also:

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

Check @codepade

Grijesh Chauhan
  • 57,103
  • 20
  • 141
  • 208
  • Comparing floating point numbers with == is a bad practice. Reason for that are the errors that accumulate from converting decimal to binary. Those errors accumulate when you start to manipulate floating numbers, making it impossible to do exact comparison. For that reason, you should never expect for a floating number to be equal to something exact. – Ignas2526 Mar 31 '15 at 06:34
  • @Ignas2526 then what would you suggest when if I some time enter in need of comparing floats. Can you give me some pointer where from read further. – Grijesh Chauhan Mar 31 '15 at 07:11
  • 2
    Here are couple pages that talk about the issue I've mentioned here: http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm – Ignas2526 Apr 17 '15 at 09:37
  • @Ignas2526 thanks I will read it, if I find something to add in my answer then will updated it. Your link will be helpful for other too. – Grijesh Chauhan Apr 17 '15 at 09:43
6

3.00 is a double, 3.00f is a float.

Erik
  • 88,732
  • 13
  • 198
  • 189
1

Adding few more combination of comparisons between float and double data types.

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;
}    

Output:

 a: Not Equal
 b: Not Equal
 c: Equal
 d: Equal
SridharKritha
  • 8,481
  • 2
  • 52
  • 43
0

That's because the default type of a floating point numeric literal - the characters 3.00 is double not float. To make this compile you have to add the suffix f (or F).

unwind
  • 391,730
  • 64
  • 469
  • 606
-1

Often the difference isn't important, as the compiler will convert the double constant into a float anyway. However, consider this:

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
  • 6,471
  • 28
  • 39
  • 1
    your answer doesn't clearly explain the difference between 3.00 and 3.00f though... – James Feb 17 '11 at 08:33
  • 1
    Exactly... You may be adding some information but your not answering the question... – James Feb 17 '11 at 08:58
  • 1
    If you try to store a double constant into a float, then yes, you will get an implicit degradation from double to float. But when it comes to expressions, the compiler cannot convert double constants into float without violating the C/C++ standard. If a double constant stands in the same expression as a float, then the "usual arithmetic conversion" rules of C/C++ demand that the float gets promoted implicitly to a double. – Lundin Feb 17 '11 at 09:42
  • 4
    Also, why do you reply with C++ when the OP is writing in C? Your example is irrelevant in C, because C doesn't have the same strict type checking as C++. – Lundin Feb 17 '11 at 09:43