Skip to main content
GameDev.net gamedev.net
🔒 Locked

"1" vs "1.0f" - makes a difference?

Started by leiavoia Jul 11, 2008 at 1:16 PM 31 replies 11.8k views
Original Post
leiavoia
leiavoia
In working with OpenGL (in C++), I gave a few functions that take floats some input like so: glFunction( 1, 7, 3 ); well, it seems to behave differently than when i specify it like this: glFunction( 1.0f, 7.0f, 3.0f ); So my question is: When assigning floating point values, does the x.xf notation make any difference than the regular "integer style" round numbers? (assuming i want a round number like "7.0") I thought the compiler implicitly converted those things! Also, is there any difference in adding the "f" at the end? (say, "0.5" vs "0.5f" ?) Thanks!
Mike.Popoloski
Mike.Popoloski
5 is an integer literal. 5.0 is a double literal. 5.0f is a float literal. It's possible that they will get converted for you by the compiler as necessary. The following code won't have any implicit casts:

int i = 5;double d = 5.0;float f = 5.0f;
Mike Popoloski | Journal | SlimDX
alvaro
alvaro
3 has type int
3.0 has type double
3.0f has type float

Exactly how some numeric types get converted to other numeric types in C++ is a complicated matter. If you are calling a function that can only accept floats, for instance, you can pass an int or a double and they will get automatically converted. However, if the function name is overloaded to accept other types, you might be calling different functions depending on exactly what types you provide.

There are some obscure bugs that can be introduced when you use the "integer style", so I recommend using 3.0 if you want a double and 3.0f if you want a float.

EDIT: Here's some code that doesn't do what you expect, because a 0' should have been 0.0':
#include <iostream>class WrappedDouble {  double x;public:  explicit WrappedDouble(double x) : x(x) {  }  operator double() const {    return x;  }};WrappedDouble five_and_a_half() {  return WrappedDouble(5.5);}int main() {  double x = false ? 0 : five_and_a_half();  std::cout << x << '\n';}
Mike.Popoloski
Mike.Popoloski
Quote:
There are some obscure bugs that can be introduced when you use the "integer style", so I recommend using 3.0 if you want a double and 3.0f if you want a float.


For example:

int windowWidth = 800;int windowHeight = 600;float aspectRatio = windowWidth / windowHeight;         // aspectRatio now equals 1float aspectRatio = (float)windowWidth / windowHeight;  // aspectRatio now equals 1.3333float aspectRatio = 800 / 600;float aspectRatio = 800.0f / 600.0f;
Mike Popoloski | Journal | SlimDX
Matias Goldberg
Matias Goldberg
Everything said is true.

But the last time I checked, OpenGL doesn't have overloaded functions (does it?). Are you sure everything else is working fine?
What compiler are you using? MSVC 6.0, 2003, 2005, 2008? Something else?

Debug & Release versions throw consistent results?

Cheers
Dark Sylinc
dmail
dmail
Quote:
Original post by Matias Goldberg
But the last time I checked, OpenGL doesn't have overloaded functions (does it?).

No because it uses C and that language can not overload functions, C++ does it with name mangling which is not available to C.

On a personal note I never bother with the zero in a float with no decimal. ie 5.f instead of 5.0f .
Cromulent
Cromulent
Quote:
Original post by alvaro
3 has type int
3.0 has type double
3.0f has type float


As far as I am aware 5.0f and 5.0 are both floats. A double is for double precision floating point numbers. The f is just there to ease readability and to suggest that you are using the GL floating point type and not the GL double type as it is rather ambiguous. Although saying that it is suggested in the particular function name, so it seems rather superfluous.
ApochPiQ
ApochPiQ
Quote:
Original post by Cromulent
Quote:
Original post by alvaro
3 has type int
3.0 has type double
3.0f has type float


As far as I am aware 5.0f and 5.0 are both floats. A double is for double precision floating point numbers. The f is just there to ease readability and to suggest that you are using the GL floating point type and not the GL double type as it is rather ambiguous. Although saying that it is suggested in the particular function name, so it seems rather superfluous.



No, alvaro is correct - 3.0 and 3.0f are different types. See MSDN.
Cromulent
Cromulent
Quote:
Original post by ApochPiQ
No, alvaro is correct - 3.0 and 3.0f are different types. See MSDN.


Not according to the OpenGL Red Book which has code looking like this:

glRectf(-25.0, -25.0, 25.0, 25.0);

which is quite obviously the floating point version of the function.

Edit : Obviously I'm talking from a C perspective.
ApochPiQ
ApochPiQ
It's already been stated in this thread that there will be an implicit cast (aka a type coercion) made by the compiler. If you crank the warning level up, you should get a warning when coercing a really large/really precise double constant to a float. For example, try passing the constant 1e50 to a function accepting a float.

Don't believe me? Try this code:
void foo(float x){  std::cout << "X is " << x << "\n";}int main(){  foo(1);  foo(1.0);  foo(1.0f);  foo(1e50);   // Warning!  std::cout << sizeof(1.0) << "\n";  std::cout << sizeof(1.0f) << std::endl;}


All three foo calls will output the same results (the fourth has undefined behaviour), while the sizeof calls will return 8 and 4 respectively (depending on the platform).
dmail
dmail
Here you go, I have taken the time to dig out K&R to show you it has always been this way and has nothing to do with OpenGL. That f is just to decorate the function for the programmer using it and for a way to overloaded the function.
Quote:

2.3 Constants ...
Floating-point constants contain a decimal point (123.4) or an exponent (1e-2) or both; their type is double, unless suffixed. The suffixes f or F indicate a float constant; l or L indicate a long double.
Matias Goldberg
Matias Goldberg
Quote:
Original post by Cromulent
Not according to the OpenGL Red Book which has code looking like this:

glRectf(-25.0, -25.0, 25.0, 25.0);

which is quite obviously the floating point version of the function.

Edit : Obviously I'm talking from a C perspective.


We ended again where we started. Definition of glRectf:

[source=c]void glRectf( GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2 );

Writting "25.0", "25.0f" or "25" in the red book won't make much difference, because the authors assume the compiler correctly converts from one type to another. They want to state how to use glRectf, not to describe detailed information about it's parameter.

You have to look at the C standard to see how the conversion is treated, not what the OGL Red Book says (unless of course, we're not talking about C language, but rather something like GLSL).

Edit: Oh, I see 'dmail' has a better answer. We replied almost at the same time
Cromulent
Cromulent
Quote:
Original post by dmail
Here you go, I have taken the time to dig out K&R to show you it has always been this way and has nothing to do with OpenGL. That f is just to decorate the function for the programmer using it and for a way to overloaded the function.
Quote:

2.3 Constants ...
Floating-point constants contain a decimal point (123.4) or an exponent (1e-2) or both; their type is double, unless suffixed. The suffixes f or F indicate a float constant; l or L indicate a long double.


Fair play. Thanks for taking the time, always useful to learn something new.

lexs
lexs
I have always just used 1.0 and almost never the f suffix when dealing with floats. Will this on modern compilers generate code that actually uses the 1.0 as a double and the casts it to a float to call the function? Or will it be cast to a float at "compile time"?
Zipster
Zipster
The compiler will do the cast, and give you a warning (unless you have a low warning level). However at work we treat all warnings as errors, so if we never used the suffix we'd all be very unhappy campers.
lexs
lexs
Quote:
Original post by Zipster
The compiler will do the cast, and give you a warning (unless you have a low warning level). However at work we treat all warnings as errors, so if we never used the suffix we'd all be very unhappy campers.


GCC 4.1.2 doesn't warn about:
float test = 1.0;

Using -Wall.
leiavoia
leiavoia
Quote:
Original post by lexs
Quote:
Original post by Zipster
The compiler will do the cast, and give you a warning (unless you have a low warning level). However at work we treat all warnings as errors, so if we never used the suffix we'd all be very unhappy campers.


GCC 4.1.2 doesn't warn about:
float test = 1.0;
Using -Wall.


ditto

I've never seen these kinds of errors.
Sc4Freak
Sc4Freak
Quote:
Original post by lexs
Quote:
Original post by Zipster
The compiler will do the cast, and give you a warning (unless you have a low warning level). However at work we treat all warnings as errors, so if we never used the suffix we'd all be very unhappy campers.


GCC 4.1.2 doesn't warn about:
*** Source Snippet Removed ***
Using -Wall.

Well, that cast is perfectly fine because the value 1.0 is exactly representable in both float and double. Try something like this:
float a = 3.14159265358979323846;float b = 1.0 / 3.0;


The compiler should warn you about truncation from double to float, because double is of a higher precision than float.
Wyrframe
Wyrframe
Quote:
Original post by MikeTacular
Actually, neither floats nor doubles can exactly represent 1.0.

IEEE 754. Read it.
RIP GameDev.net: launched 2 unusably-broken forum engines in as many years, and now has ceased operating as a forum at all, happy to remain naught but an advertising platform with an attached social media presense, headed by a staff who by their own admission have no idea what their userbase wants or expects.Here's to the good times; shame they exist in the past.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.