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.

有帮助吗?

解决方案

Conversions between data types are well defined in Java Language Specification (see section Conversions and Promotions).

I believe your case falls under 5.1.3. Narrowing Primitive Conversion where you can see that:

  • First your float will be rounded to an integer using IEEE 754 round-toward-zero mode (explained here) and
  • It will be assigned the largest or smallest representable integer value depending on if the value is too small or too large.
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top