让我们进行一个实验:
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
我们可以得出结论,最大的可转换为int
的float
是2147483520
。最大的可转换为float
并且再转回int
的int
是2147483583
;
如果我们尝试将2147483583 + 1 = 2147483584
强制转换,我们将得到2147483650f
,如果我们尝试将其转回int
,会引发异常。
int overflow = 2147483583 + 1
int back = checked((int)(float) overflow)
或者甚至更多
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
(无异常处理;如果float
超出范围,则返回int.MaxValue
或int.MinValue
):
public static int ClampToInt(this float x) =>
x > 2147483520f ? int.MaxValue
: x < -2147483650f ? int.MinValue
: (int) x;
public static int ClampToInt(this double x) =>
x > int.MaxValue ? int.MaxValue
: x < int.MinValue ? int.MinValue
: (int) x;
float
中,您可以存储的最大值比int.MaxValue
小的值是2147483000f
。在超过这个值之前,您可以使用的最大 常量float
文字是2147483456f
,即使添加一小部分也会使其超过。我通过实验找到了这些值,因此无法回答如何以好的方式获得这些值。 - Lasse V. Karlsen2147483000f
是小于int.MaxValue
的最大浮点数。那么2147483520f
呢?请参见此处。 - Sebastian Schumann2147483583f
,然后它就翻了,我猜之前测试时我的代码有 bug。这最终变成了字节 ff-ff-ff-4e,将值增加 1 则变为00-00-00-4f
,被认为更高。而3583
和3520
只是在字面上的区别,无论如何都存储为3520
。 - Lasse V. KarlsenDBL_MANT_DIG
。 - Eric Postpischil