Purpose of a .f appended to a number?
Without the .f
the number gets interpreted as an integer, hence 1/3
is (int)1/(int)3
=> (int)0
instead of the desired (float)0.333333
. The .f
tells the compiler to interpret the literal as a floating point number of type float. There are other such constructs such as for example 0UL
which means a (unsigned long)0
, whereas a plain 0
would be an (int)0
.
The .f
is actually two components, the .
which indicates that the literal is a floating point number rather than an integer, and the f
suffix which tells the compiler the literal should be of type float rather than the default double type used for floating point literals.
Disclaimer; the "cast construct" used in the above explanation is not an actual cast, but just a way to indicate the type of the literal.
If you want to know all about literals and the suffixes you can use in them, you can read the C++ standard, (1997 draft, C++11 draft, C++14 draft, C++17 draft) or alternatively, have a look at a decent textbook, such as Stroustrup's The C++ Programming Language.
As an aside, in your example (float)1/3
the literals 1
and 3
are actually integers, but the 1 is first cast to a float by your cast, then subsequently the 3 gets implicitly cast to a float because it is a righthand operand of a floating point operator. (The operator is floating point because its lefthand operand is floating point.)
Why is the letter f used at the end of a float no.?
The f
indicates it's a floating point literal, not a double literal (which it would implicitly be otherwise.) It hasn't got a particular technical name that I know of - I tend to call it the "letter suffix" if I need to refer to it specifically, though that's somewhat arbitrary!
For instance:
float f = 3.14f; //Compiles
float f = 3.14; //Doesn't compile, because you're trying to put a double literal in a float without a cast.
You could of course do:
float f = (float)3.14;
...which accomplishes near enough the same thing, but the F is a neater, more concise way of showing it.
Why was double chosen as the default rather than float? Well, these days the memory requirements of a double over a float aren't an issue in 99% of cases, and the extra accuracy they provide is beneficial in a lot of cases - so you could argue that's the sensible default.
Note that you can explicitly show a decimal literal as a double by putting a d
at the end also:
double d = 3.14d;
...but because it's a double value anyway, this has no effect. Some people might argue for it advocating it's clearer what literal type you mean, but personally I think it just clutters code (unless perhaps you have a lot of float literals hanging around and you want to emphasise that this literal is indeed meant to be a double, and the omission of the f isn't just a bug.)
How come some people append f to the end of variables?
It's a way to specify that number has to be interpreted as a "float", not a "double" (which is the standard for C++ decimal numbers and uses up twice the memory).
This discussion could be of help:
http://www.cplusplus.com/forum/beginner/24483/
When does appending an 'f' change the value of a floating constant when assigned to a `float`?
This is a self answer per Answer Your Own Question.
Appending an f
makes the constant a float
and sometimes makes a value difference.
Type
Type difference: double
to float
.
A well enabled compiler may emit a warning when the f
is omitted too.
float f = 3.1415926535897932; // May generate a warning
warning: conversion from 'double' to 'float' changes value from '3.1415926535897931e+0' to '3.14159274e+0f' [-Wfloat-conversion]
Value
To make a value difference, watch out for potential double rounding issues.
The first rounding is due to code's text being converted to the floating point type.
the result is either the nearest representable value, or the larger or smaller representable value immediately adjacent to the nearest representable value, chosen in an implementation-defined manner. C17dr § 6.4.4.2 3
Given those two choices, a very common implementation-defined manner is to convert the source code text to the closest double
(without the f
) or to the closest float
with the f
suffix. Lesser quality implementations sometimes form the 2nd closest choice.
Assignment of a double
FP constant to a float
incurs another rounding.
If the value being converted is in the range of values that can be represented but cannot be represented exactly, the result is either the nearest higher or nearest lower representable value, chosen in an implementation-defined manner. C17dr § 6.3.1.4 2
A very common implementation-defined manner is to convert the double
to the closest float
- with ties to even. (Note: compile time rounding may be affected by various compiler settings.)
Double rounding value change
Consider the case when source code uses a value very close to half-way between 2 float
values.
Without an f
, the rounding of code to a double
may result in a value exactly half-way between 2 float
s. The conversion of the double
to float
then could differ from "with an f
".
With an f
, the conversion results in the closest float
.
Example:
#include <math.h>
#include <stdio.h>
int main(void) {
float f;
f = 10000000.0f;
printf("%.6a %.3f 10 million\n", f, f);
f = nextafterf(f, f + f);
printf("%.6a %.3f 10 million - next float\n", f, f);
puts("");
f = 10000000.5000000001;
printf("%.6a %.3f 10000000.5000000001\n", f, f);
f = 10000000.5000000001f;
printf("%.6a %.3f 10000000.5000000001f\n", f, f);
puts("");
f = 10000001.4999999999;
printf("%.6a %.3f 10000001.4999999999\n", f, f);
f = 10000001.4999999999f;
printf("%.6a %.3f 10000001.4999999999f\n", f, f);
}
Output
0x1.312d00p+23 10000000.000 10 million
0x1.312d02p+23 10000001.000 10 million - next float
// value value source code
0x1.312d00p+23 10000000.000 10000000.5000000001
0x1.312d02p+23 10000001.000 10000000.5000000001f // Different, and better
0x1.312d04p+23 10000002.000 10000001.4999999999
0x1.312d02p+23 10000001.000 10000001.4999999999f // Different, and better
Rounding mode
The issue about double1 rounding is less likely when the rounding mode is up, down or towards zero. Issue arises when the 2nd rounding compounds the direction on half-way cases.
Occurrence rate
Issue occurs when code converts inexactly to a double
that is very near half-way between 2 float
values - so relatively rare. Issue applies even if the code constant was in decimal or hexadecimal form. With random constants: about 1 in 230.
Recommendation
Rarely a major concern, yet an f
suffix is better to get the best value for a float
and quiet a warning.
[Update 2022]
The issue is further complicated under 2 conditions:
FLT_EVAL_METHOD == 2
, then the constant maybe evaluated usinglong double
math.Evaluation of floating point constants may ignore decimal digits past a certain precision. This is allowed in C and IEEE 754. Typically this is
XXX_DECIMAL_DIG + 3
digits (e.g. 20 fordouble
).
These complications change the chance of seeing this issue. Still the conclusion remains: append f
to get the best float
constant.
1 double here refers to doing something twice, not the the type double
.
f after number
CGRect frame = CGRectMake(0.0f, 0.0f, 320.0f, 50.0f);
uses float constants. (The constant 0.0 usually declares a double in Objective-C; putting an f on the end - 0.0f - declares the constant as a (32-bit) float.)
CGRect frame = CGRectMake(0, 0, 320, 50);
uses ints which will be automatically converted to floats.
In this case, there's no (practical) difference between the two.
Why do you need to append an L or F after a value assigned to a C++ constant?
Floating-point constants have type double
by default in C++. Since a long double
is more precise than a double
, you may lose significant digits when long double
constants are converted to double
. To handle these constants, you need to use the L
suffix to maintain long double
precision. For example,
long double x = 8.99999999999999999;
long double y = 8.99999999999999999L;
std::cout.precision(100);
std::cout << "x=" << x << "\n";
std::cout << "y=" << y << "\n";
The output for this code on my system, where double
is 64 bits and long double
96, is
x=9
y=8.9999999999999999895916591441391574335284531116485595703125
What's happening here is that x
gets rounded before the assignment, because the constant is implicitly converted to a double
, and 8.99999999999999999
is not representable as a 64-bit floating point number. (Note that the representation as a long double
is not fully precise either. All of the digits after the first string of 9
s are an attempt to approximate the decimal number 8.99999999999999999
as closely as possible using 96 binary bits.)
In your example, there is no need for the L
constant, because 3.0
is representable precisely as either a double
or a long double
. The double
constant value is implicitly converted to a long double
without any loss of precision.
The case with F
is not so obvious. It can help with overloading, as Zan Lynx points out. I'm not sure, but it may also avoid some subtle rounding errors (i.e., it's possible that encoding as a float
will give a different result from encoding as a double
then rounding to a float
).
Java - Why does append F to `float a=0.32F` tell it to store 32-bit float in a, but doing `float a = 0.32` tell it you want to store 64 bit double?
The 32/64 discussion here relates to the literal, not the variable.0.234F
is a 32bit float literal, while 0.234
is a 64bit double literal.
So if we reexamine those two statements:
float ratio = 0.234F
means "take the 32bit float value of 0.234 and place it in the variable ratio
".float ratio = 0.234
means "take the 64bit double value of 0.234 and place it in the variable ratio
" - which, as you've seen, is not possible and results in a compilation error.
What do F and D mean at the end of numeric literals?
Means that these numbers are doubles and floats, respectively. Assume you have
void foo(int x);
void foo(float x);
void foo(double x);
and then you call
foo(5)
the compiler might be stumped. That's why you can say 5
, 5f
, or 5.0
to specify the type.
what does the .f in 1000.f mean? c++
1000
is an int
literal.
1000.
is a double
literal.
1000.f
is a float
literal.
Related Topics
Is There a C++11 Syntax File for Vim
How to Use an Enum Value in a Switch Statement in C++
How to Convert Rgb -> Yuv -> Rgb (Both Ways)
How to Write the Following as a C++ MACro
Specification of Source Charset Encoding in Msvc++, Like Gcc "-Finput-Charset=Charset"
What's the Time Complexity of Iterating Through a Std::Set/Std::Map
Reinterpret_Cast Between Char* and Std::Uint8_T* - Safe
Does Std::Atomic<Std::String> Work Appropriately
Getline Keeps on Getting Newline Character. How to Avoid This
What's the Usual Way of Controlling Frame Rate
How Do Static Variables in Lambda Function Objects Work
Accessing Elements of a Cv::Mat with At<Float>(I, J). Is It (X,Y) or (Row,Col)
Debug and Release Library Linking with Cmake (Visual Studio)
Difference in Initializing and Zeroing an Array in C/C++
Disabling G++'s Return-Value Optimisation