Reputation:
I'm writing a program to calculate the result of numbers:
int main()
{
float a, b;
cin >> a >> b;
float result = b + a * a * 0.4;
cout << result;
}
but I have a warning at a * a
and it said Warning C26451 Arithmetic overflow: Using operator '*' on a 4 byte value and then casting the result to a 8 byte value. Cast the value to the wider type before calling operator '*' to avoid overflow (io.2).
Sorry if this a newbie question, can anyone help me with this? Thank you!
Upvotes: 0
Views: 789
Reputation: 28300
I read the question as "how to change the code to remove the warning?".
If you take the advice in the warning's text literally:
float result = b + (double)a * a * 0.4;
But this is nonsense — if an overflow happens, your result will probably not fit into float result
.
It looks like in your case overflow is not possible, and you feel perfectly fine doing all calculations with float
. If so, just write 0.4f
instead of 0.4
— then the constant will have float
type (instead of double
), and the result will also be float
.
If you want to "fix" the problem with overflow
double result = b + (double)a * a * 0.4;
But then you must also change the following code, which uses the result
. And you don't remove the possibility of overflow, you just make it much less likely.
Upvotes: 0
Reputation: 63946
Let's look at the error message.
Using operator '*' on a 4 byte value
It is describing this code:
a * a
Your float
is 4 bytes. The result of the multiplication is 4 bytes. And the result of a multiplication may overflow.
and then casting the result to a 8 byte value.
It is describing this code:
(result) * 0.4;
Your result is 4 bytes. 0.4
is a double
, which is 8 bytes. C++ will promote your float
result to a double
before performing this multiplication.
So...
The compiler is observing that you are doing float
math that could overflow and then immediately converting the result to a double
, making the potential overflow unnecessary.
Change the code to this to remove the float
to double
to float
conversions.
float result = b + a * a * 0.4f;
Upvotes: 2
Reputation: 81307
In the C language as described in the first edition of K&R, all floating-point operations were performed by converting operands to a common type (specifically double
), performing operations with that type, and then if necessary converting the result to whatever type was needed. On many platforms, that was the most convenient and space-efficient way of handling floating-point math. While the Standard still allows implementations to behave that way, it also allows implementations to perform floating-point operations on smaller types to be performed using those types directly.
As written, the subexpression a * a * 0.5;
would be performed by multiplying a * a
together using float
type, then multiply by a value 0.5 which is of type double
. This latter multiplication would require converting the float
result of a * a
to double. If e.g. a
had been equal to 2E19f, then performing the multiply using type float
would yield a value too large to be represented using that type. Had the code instead performed the multiplication using type double
, then the result 4E38 would be representable in that type, and the result of multiplying that by 0.5 (i.e. 2E38) would be within the range that is representable by float
.
Note that in this particular situation, the use of float
for the intermediate computations would only affect the result if a
was within narrow ranges of very large or very small. If instead of multiplying by 0.5 one had multiplied by other values, however, the choice of whether to use float
or double
for the first multiplication could affect the accuracy of rounding. Generally, using double
for both multiplies would yield slightly more accurate results, but at the expense of increased execution time. Using float
for both may yield better execution speed, but at the result of reduced precision. If the floating-point constant had been something that isn't precisely representable in float
, converting to double
and multiplying by a double
constant may yield slightly more accurate results than using float
for everything, but in most cases where one would want that precision, one would also want the increased position that would be achieved by using double
for the first multiply as well.
Upvotes: 1