Take the following piece of code:
const float fValue = 5.5f;
const float globalMin = 0.0f;
const float globalMax = 5.0f;
float vFactor = (float)(2e9 / (globalMax - globalMin));
int iValue = (int)((fValue - globalMin) * vFactor);
That last line results in a value which overflows an int
. In C#, the result is unspecified:
- 6.2.1 Explicit numeric conversions
- For a conversion from float or double to an integral type, the processing depends on the overflow checking context (§7.6.12) in which the conversion takes place:
- In an unchecked context, the conversion always succeeds, and proceeds as follows.
- If the value of the operand is NaN or infinite, the result of the conversion is an unspecified value of the destination type.
- Otherwise, the source operand is rounded towards zero to the nearest integral value. If this integral value is within the range of the destination type then this value is the result of the conversion.
- Otherwise, the result of the conversion is an unspecified value of the destination type.
In java... well, I don't know, that's why I'm here. I know how typical integer overflow (i.e., Integer.MAX_VALUE + 1
) is handled, but I can't find anything in the spec which refers to overflow as the result of a conversion from a float
.
In my tests (Java) the result of that last line is Integer.MAX_VALUE
which tells me that something more is going on as I would expect it to be -2094967296
if the value simply rolled over. It looks like Java is truncating to MAX_VALUE
upon overflow.
EDIT: Thanks to @Pascal Cuoq for pointing out that the SSE2 assembly instruction that truncates a float to int produces INT_MIN on overflow. I'm going to fix the bug on the C# side, but I am still curious as to where/if this behavior is specified by Java.