Why Floating Point Value Such as 3.14 Are Considered as Double by Default in Msvc

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

floats convert to doubles 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



Leave a reply



Submit