Reputation: 544
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?
Upvotes: 4
Views: 3071
Reputation: 42032
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
f
on float valueUpvotes: 2
Reputation: 108880
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
Upvotes: 8
Reputation: 793339
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;
Upvotes: 5
Reputation: 361812
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.
Upvotes: 2
Reputation: 26281
The default assumption is double
. specifying f
suffix ensures that it will be interpreted as a float
Upvotes: 2
Reputation: 477680
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);
Upvotes: 4