Why floating point value such as 3.14 are considered as double by default in MSVC?
That's what the C++ (and C) standard decided. Floating point literals are of type double, and if you need them to be floats, you suffix them with a f
. There doesn't appear to be any specifically stated reason as to why, but I'd guess it's a) For compatibility with C, and b) A trade-off between precision and storage.
2.13.3 Floating literals The type
of a floating literal is double unless
explicitly specified by a suffix. The
suffixes f and F specify float, the suffixes l and L specify long double.
If the scaled value is not in the
range of
representable values for its type, the program is ill-formed.
Why does auto deduce this variable as double and not float?
Type of literal 3.5
is double
. For float
please use 3.5f
You can play with this snippet to see various type information.
why sizeof(13.33) is 8 bytes?
Those are the rules of the language.
13.33 is a numeric literal. It is treated as a double because it is a double. If you want 13.33 to be treated as a float literal, then you state 13.33f.
13.33 is a double literal. If sizeof(float) == 4, sizeof(13.33f) == 4 should also hold because 13.33f is a float literal.
Should I use double or float?
If you want to know the true answer, you should read What Every Computer Scientist Should Know About Floating-Point Arithmetic.
In short, although double
allows for higher precision in its representation, for certain calculations it would produce larger errors. The "right" choice is: use as much precision as you need but not more and choose the right algorithm.
Many compilers do extended floating point math in "non-strict" mode anyway (i.e. use a wider floating point type available in hardware, e.g. 80-bits and 128-bits floating), this should be taken into account as well. In practice, you can hardly see any difference in speed -- they are natives to hardware anyway.
Why the compiler won't automatically assume seemingly float const value to float
The literal 1.333
is a double
, not a float
. The conversion from double
to int
is considered to be as good as that of double
to float
, so resulting in the ambiguous overload error. To disambiguate, pass a float:
funA(1.333f);
If you wanted to be sure to dispatch calls with double
arguments to funA(float)
, then you can follow @JamesKanze's example from the comments:
void funA( double v )
{
return funA( static_cast<float>( v ) );
}
but note that the range of a double
is likely to be greater than that of a float
.
Are there any real life situations where declaring all floating point literals as double causes real problems in C++?
I don't have a good "real-life" example at hand. Instead I want to try to convince you with a hopefully simple example.
Lets assume all function with overloads for float
and double
do "the right thing":
void f(float x) {/*do something*/};
void f(double x) {/*do the same thing*/};
Moreover, when only one of the overloads is available, we can call it with a literal of either type:
void f_float(float x) {/*do something*/};
void f_double(double x) {/*do the same thing*/};
f_float(3.0); // ok
f_float(3.0f); // ok
f_double(3.0); // ok
f_double(3.0f); // ok
float
s convert to double
s and vice versa.
If all code is fine with either float
or double
, this is end of story. However, you don't need to do something "funny" to get the code to break.
I haven't found any satisfactory answer that shows an actually relevant situation, where the distinction is important.
The distinction is important when the type of the literal is used to infer the type of something else. Being able to convert between double
and float
is not all you need to be able to replace any float
literal with a double
literal without breaking code.
In the above example f_float
can be called with either 3.0
or 3.0f
. Now suppose you have a function that only accepts a std::vector<float>
:
void bar(const std::vector<float>& x){}
and something that given a single value, constructs a vector:
template <typename T>
std::vector<T> make_vect(const T& t){ return {T{}}; }
Then the type of the literal makes the code either fail or pass:
bar(make_vect(0.3f));
//bar(x.make_vect(0.3)); // ERROR
Complete Example.
TL;DR
The whole point is just that you can convert between float
and double
, but in general there is no conversion available between some_template<float>
and some_template<double>
. The type of a literal can be relevant, even though you don't mind conversions between float
and double
. Changing a 3.0f
to a 3.0
can make code break, that was fine otherwise
float data type(5.0) being assigned 8 bytes rather that 4 using sizeof operator in C
Because all floating point literals default to double
. If you want it to be a float
then use the f
suffix as in 5.0f
.
Read e.g. this floating point constant (literal) reference for more information.
Floating point numbers are printing only the integral part
It's because as both i
and 100
are integers, the compiler does integer division.
The easiest way to solve this is to use the double
literal 100.0
instead:
cout << (x = i/100.0) << endl;
Floating point numbers are printing only the integral part
It's because as both i
and 100
are integers, the compiler does integer division.
The easiest way to solve this is to use the double
literal 100.0
instead:
cout << (x = i/100.0) << endl;
Related Topics
Std::Optional Specialization for Reference Types
Why Does VS Not Define the Alternative Tokens for Logical Operators
Is Std::Pair<Int, Std::String> Ordering Well-Defined
Check If Member Exists Using Enable_If
Near Constant Time Rotate That Does Not Violate the Standards
Prevent User Process from Being Killed with "End Process" from Process Explorer
Writing Utf16 to File in Binary Mode
Default Class Inheritance Access
Connected Components in Opencv
Why There Is No Placement Delete Expression in C++
Fast N Choose K Mod P for Large N
What Is the Correct Way of Reading from a Tcp Socket in C/C++
Error: Use of Deleted Function
How to Initialize a Static Const Member in C++
Mingw .Exe Requires a Few Gcc Dll's Regardless of the Code
Which Boost Features Overlap with C++11
Explain Morris Inorder Tree Traversal Without Using Stacks or Recursion