Давайте проведем эксперимент :
float best = 0f;
for (int i = 2147483000; ; ++i)
{
float f = (float)i;
try
{
checked
{
int v = (int)f;
}
best = f;
}
catch (OverflowException)
{
string report = string.Join(Environment.NewLine,
$" max float = {best:g10}",
$"min overflow = {f:g10}",
$" max int = {i - 1}");
Console.Write(report);
break;
}
}
Результат
max float = 2147483520
min overflow = 2147483650
max int = 2147483583
Таким образом, мы можем заключить, что максимальное значение float
, которое может быть приведено к int
, равно 2147483520
. Максимум int
, который может быть приведен к float
и обратно к int
, равен 2147483583
;
если мы попытаемся разыграть 2147483583 + 1 = 2147483584
, мы получим 2147483650f
, который выдаст исключение, если мы попытаемся привести его к int
.
int overflow = 2147483583 + 1;
int back = checked((int)(float) overflow); // <- throws exception
или даже
float f_1 = 2147483583f; // f_1 == 2147483520f (rounding)
int i_1 = checked((int) f_1); // OK
float f_2 = 2147483584f; // f_2 == 2147483650f (rounding) > int.MaxValue
int i_2 = checked((int) f_2); // throws exception
Наконец, float
в int
преобразование (без исключений; int.MaxValue
или int.MinValue
, если float
имеет значение вне диапазона ):
// float: round errors (mantissa has 23 bits only: 23 < 32)
public static int ClampToInt(this float x) =>
x > 2147483520f ? int.MaxValue
: x < -2147483650f ? int.MinValue
: (int) x;
// double: no round errors (mantissa has 52 bits: 52 > 32)
public static int ClampToInt(this double x) =>
x > int.MaxValue ? int.MaxValue
: x < int.MinValue ? int.MinValue
: (int) x;