Reputation: 19612
I have code that, reduced to its essence, comes down to:
int x = 5;
x *= 0.5;
Compiling this with Visual Studio, I get a warning C4244 about possible loss of data - of course, because (simplified) the multiplication of an int by a double results in a double which is then cast to an int, losing the non-integer part.
My question is, is there C++ syntax to indicate that this the intended behavior, so as to silence the warning (I know about pragma push/pop to disable the warning, I think it's clearer to indicate that this is actually intended behavior, and that I'm not just suppressing warnings).
The long-form would be to cast explicitly after the multiplication like so:
x = (int)(x * 0.5);
but the compound-operator notation is easier to read.
So, is there a way to cast like this? I've tried putting "(int)" in every location I could think of, but none of them seem to be valid C++ :(
Upvotes: 5
Views: 1054
Reputation: 111120
As per the OP's comments, you are probably best advised to use an appropriate function from <cmath>
depending on the sort of rounding behavior you want (biased/un-biased).
For example floor
typically does biased rounding (biased towards negative infinity, because it always chooses the lower integer number) i.e. floor( -7.5 )
would give you -8
and you will need to roll-your-own should you want a symmetric rounding i.e. want floor( -7.5 )
to be -7
(as floor( 7.5 )
gives 7
).
round
however can be tweaked to produce an unbiased rounding. Typically, it would produce 10
from round( 10.3 )
, 11
from round( 10.6 )
(or greater). There is still the problem with rounding at the middle (tie-breaking) i.e. what round( 10.5 )
should provide (it would typically produce 11
). In case, this behavior is not suitable for you, you may want to look up at some alternatives like Banker's Rounding/Alternate Rounding etc.
Upvotes: 1
Reputation: 5263
The result of a multiplication of an int and a float is a float.
If you want to convert the int to a float, you are likely to need to round the float to remove the decimal value. If you simply cast it, you can have rounding errors.
For example this function does rounding (there are other way of rounding numbers):
int round(float x)
{
return static_cast<int>((x > 0.5) ? ceil(x) : floor(x));
}
Then you just have to call it that way:
int x = 5;
float y = 0.33f;
x = round(x * y);
And you have no warnings and the float is properly rounded and cast to an int.
I don't have a proper solution for the *=
operator with a good rounding, so with this solution you will have to replace the *=
.
Upvotes: 0
Reputation: 22624
The warning is in place - you should be warned of the possible loss of data.
Any ways to avoid the warning involves using a syntax which clearly expresses your intent. This can be done in the following ways:
x = static_cast<int>(x * 0.5);
With the unary operator *
you cannot suppress the warning easily because that operator was intended to be user in a clear and straighforward way, with no casting involved - and your case does not fulfill this requirement. So it is a good thing that you cannot do it.
Upvotes: 2
Reputation: 129754
Instead of multiplying by 0.5, divide by 2. With two int
s integer division will be used and there will be no warning.
And if you really want to multiply by floats/doubles, don't use int
to store the result.
Upvotes: 3