Sign in to follow this  
Servant of the Lord

Type Casting

Recommended Posts

Every time I want to do something simple, like multiply a int by a float, I have to change this:
myInt *= myFloat;
To this:
myInt = (int)((float)myInt * myFloat);
I definitely don't want to turn off compiler warnings entirely; those are helpful when I make a mistake. I'm just wanting to know if there is a easier way to convert from int to float? The above code snippet is fairly simple, but here's a copy + paste of something almost as basic that I just wrote in my code:
damage = (int)((float)damage * (1.0f - ((float)distanceFromEnemy / (float)(weapon->range+1))));
The nested parentheses irritate me. Would you break it up? How would you write it?
float damageModifyer = (1.0f - ((float)distanceFromEnemy / (float)(weapon->range+1)));
damage = (int)((float)damage * damageModifyer);
Without the need of typecasting, it looks very clean:
damage *= (1.0f - (distanceFromEnemy / (weapon->range+1)));
Mainly, it's the inability to use *=, /=, +=, and -=, when typecasting that makes it look most messy. It'd be great if I could auto typecast for a single line only. Something like:
(typecast) damage *= (1.0f - (distanceFromEnemy / (weapon->range+1)));

Share this post


Link to post
Share on other sites
It won't solve all problems, but you shouldn't need to cast every variable in the calculations: if one of the values involved is a float, all others should be cast to float implicitly (and without a warning?):


myInt = int(myInt * myFloat);


The cast back is needed (to silence the warnings), since you will be losing data here.

As a whole, you might just try to assign floats to int in as few places as possible.

Share this post


Link to post
Share on other sites
Warning are inherently compiler dependent in C++, which means that ways around them are also compiler dependent. In MSVC you can mark a block of code to not give you conversion warnings by surrounding it with the right set of pragmas. Ex:

#pragma warning(push)
#pragma warning(disable:4244)
int i = 1;
float f = 2.0f;
i *= f;
#pragma warning(pop)

Share this post


Link to post
Share on other sites
Quote:
Original post by visitor
It won't solve all problems, but you shouldn't need to cast every variable in the calculations: if one of the values involved is a float, all others should be cast to float implicitly (and without a warning?):

myInt = int(myInt * myFloat);
That's very helpful, I thought I had to manually cast each int to a float and then cast the entire result back to a int afterward. Thank you! That alone makes the code more readable.
Quote:
Original post by SiCrane
Warning are inherently compiler dependent in C++, which means that ways around them are also compiler dependent. In MSVC you can mark a block of code to not give you conversion warnings by surrounding it with the right set of pragmas.
Is there some library online, or just a header file, that creates macroes for easily disabling/re-enabling warnings on most of the major compilers and platforms? If you aren't aware of one just offhand, don't bother (I'm just curious for future needs). Visitor's post gave me what I needed. [smile]

Thanks guys.

Share this post


Link to post
Share on other sites
Quote:
Original post by Zahlman
Have you considered just using floats for all the variables in question? What problems would it cause?

Well, I'll have to typecast them somewhere along the line. distanceFromEnemy is passed as a argument to the function, but that argument could be made a float. Both weapon->range and damage are retrieved from a structure that holds information about the weapon being used. This wont be the only function that uses them, and I don't want to make them floats in the structure for just this block of code.
Quote:
Original post by dmatter
One alternative is to just rework your equation:

damage -= (damage * distanceFromEnemy) / (weapon->range + 1);

That's a much sleeker way of writing it, I'll use that. This wasn't the only time where I was needing alot of typecasting though, and visitor's example of how to use typecasting will cut down enough of the manual typecasting to satisfy me for any other cases I might encounter.

Share this post


Link to post
Share on other sites
Note that all you accomplish by forcibly casting from a float to an int is making the warning go away. The risk of data loss will still be there; the compiler will just stop telling you about it.

Share this post


Link to post
Share on other sites
Quote:
Original post by Servant of the Lord
Quote:
Original post by Zahlman
Have you considered just using floats for all the variables in question? What problems would it cause?

Well, I'll have to typecast them somewhere along the line.


Why? :)

Share this post


Link to post
Share on other sites
I am always very explicit in my casts, using the actual static_cast<> feature instead of the C style casts. Yes, it makes the code a bit more verbose, but there is then no question as to your intention. I find it makes hunting down cast related bugs easier.

If you find you're doing a lot of casts, take a look at the data types you're using to begin with and perhaps change them. In your particular case, why not have damage, distance, and range be floats? I could easily see the case where you may want fractional damage, distance, and range. You can always round to an integer for some final output.

Share this post


Link to post
Share on other sites
Quote:
Original post by scjohnno
Note that all you accomplish by forcibly casting from a float to an int is making the warning go away. The risk of data loss will still be there; the compiler will just stop telling you about it.

By risk of data, do you mean when casting from float to int, cutting off the decimal points, and when casting from int to float, potentially 'random' values if my int is a large value? I'm, in the parts of the code I'm dealing with, using rather small values (under 1000), and I don't care about the decimal point loss (in this particular code, I mean), I don't need great precision. It's something I need to remember, though. And, like I mentioned in a post above, I definitely don't want to disable the warnings for the entire project, or even the entire file, just specific lines (which casting takes care of).

Quote:
Original post by Zahlman
Quote:
Original post by Servant of the Lord
Well, I'll have to typecast them somewhere along the line.

Why? :)

What benefit do I get from making the entire game (or most of it) use floats instead of ints, when I only need a few functions to use them? It's a good point you are making, and I'd follow that advice, and make the variables floats if they were contained just in that function, or that one class.
However, that's not the case. Due to poor design, or rather, no actual planning how my game works, and coding as I go along, the code is a mess.

The class isn't contained within itself. The class is tightly coupled (I believe that's the term) with 2 other classes and a struct, and receives values as ints from even more classes. I'd have to change a great deal of code, just to make these 2 or 3 spots avoid type casting. It'd be a whole different story if the classes didn't rely on each other so much.

(You can stop reading here if you want - Everything below this line can be ignored if you don't care for my excuses. [smile])


It's my first real game that I haven't stopped working on halfway through; it's pretty horrible code. I don't intend to make the same mistake on my next project, especially not after having read the book 'Code Complete'. I don't feel up to rewriting it entirely though, so I intend to finish the game as it is, since I've gotten most of it completed and working. On whatever my next game is, I am going to try and figure out how the code itself will work before actually coding it. (Designing ahead of time not just how the game will play(which I did do on this current project), but also how it'd work behind the scenes)

The code is so horrible that instead of having some kind of message system, to pass information around, every class can access any other class via pointers by accessing their owner class. So 'Ship' points up to 'ShipManager', which points up to 'Game' which points down to 'PlayingField'.
The game is about 90% complete, having whittled my 'ToDo' list down almost entirely, and getting every major (and most minor) features implemented except for ship-to-ship attacking. If I was to rewrite the majority of the code, I'd rather just scrap the project and start fresh on a new one. But I feel I really need to finish this project before starting on something new, to break out of my cycle of unfinished games. Since it's so close to completion, I'm just going to finish it and get it over with.

Share this post


Link to post
Share on other sites
Quote:
Original post by Servant of the Lord
when casting from int to float, potentially 'random' values if my int is a large value?

The other way around. A float's maximum value is 3.40282e38 (on my install of VS2008 anyway), whereas int's is much less at 2147483647.

It's pretty unlikely that it'll be a problem, but the compiler is letting you know of the possibility just in case. It's more of an issue if you're ever using a small type such as char, or are casting from a double to a float. Weird things can happen when a variable in your code gets a seemingly random value, and it's not the easiest bug to identify.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this