Is there a functional difference between "2.00" and "2.00f"?

2.8k views Asked by At

I ask because I am using the Box2D library, which calls for mostly float arguments. Although I see a lot of example code that uses the 0.00f format, I am not quite sure if there is an actual difference between that and plain old 0.00.

Will I be hurting myself later on by not appending the additional f? Is it a speed thing? Is there some sort of connotation that would need the f addend when others wouldn't?

TL;DR: Why should I be using 0.00f instead of 0.00?

6

There are 6 answers

7
CodesInChaos On BEST ANSWER

The f suffix makes it a single precision(float) literal instead of a double precision literal. This usually means 32 bit instead of 64 bit floats.

Floating-point constants default to type double. By using the suffixes f or l (or F or L — the suffix is not case sensitive), the constant can be specified as float or long double, respectively.

http://msdn.microsoft.com/en-us/library/tfh6f0w2(v=VS.100).aspx

0
Sarfaraz Nawaz On

The type of 2.00 is double, and the type of 2.00f is float.

The suffix f turns the literal 2.00 into a float type, decreasing its precision. Otherwise, literal is double type.

0
Kerrek SB On

As long as you assign them to a float, there's absolutely no difference, since the value is representable precisely and correctly in all numeric types.

The important difference is the type of the literal, which is double for 2.0, float for 2.0f and int for 2. So it makes a difference in argument type deduction:

void foo(int) { cure_cancer(); };
void foo(float) { wipe_hard_disk(); }
void foo(double) { exit(0); }

foo(2);
foo(2.0f);
foo(2.0);
0
Foo Bah On

The default assumption is double. specifying f suffix ensures that it will be interpreted as a float

0
CB Bailey On

There is a difference. 2.00 has type double and 2.00f has type float. The exact precision and format implications of this depends on your platform. Whether the use of one over the other makes a practical difference in your code depends on the context in which it is used.

As an initializer for an explicity typed variable (of a fundamental numeric type), there will be no difference but when used in a function call it might potentially affect which overload or template specialization is used.

Obviously, when used as an initializer in a declaration using the auto type-specifier or as an expression in a decltype-specifier, the type of the object being declared will be affected.

decltype(2.00) x = 2.00f; // confusing
decltype(2.00f) y = 2.00; // also confusing

auto d = 2.00;
auto f = 2.00f;
2
phuclv On
  • The suffix affects the type, which changes how a statement is parsed

    This not only changes type deduction result via decltype and function overload selection as others said, but also how an expression is evaluated

    For example 2.0 * x / 3 is done in double precision, and 2.0f * x / 3 is done in float precision when x is float. That may lead to different results because doing in a higher precision will reduce any intermediate errors. It also affects performance greatly on FPU-less systems or systems with an FPU for float only, and it's a thing embedded programmers need to care about. Demo on Godbolt

    Here I'm assuming the FLT_EVAL_METHOD macro is set so that floating-point types are not evaluated in a higher precision. But even if FLT_EVAL_METHOD >= 1 then the result might still be different with and without the suffix, because of the next point:

  • The suffix also affects the value

    In C++ the value must be rounded correctly to the nearest value in the destination type. So for example when we have

    float f1 = 8388608.5000000009f;
    float f2 = 8388608.5000000009;
    

    then f1 and f2 will have different values because the suffix prevents double rounding (meaning rounding twice, not the type double) from happening in f2 (decimal → double → float). The decimal value is rounded to the nearest float value directly in f1 (decimal → float) without going through double. Print the values with more precision and you'll see

    Another example:

    f1 = 7.038531e-26f;
    f2 = 7.038531e-26;
    

    There are many other examples that you can see in the demo

See also