将long.MaxValue强制转换为int和将float.MaxValue强制转换为int有什么区别?

12

我试图理解一些数据类型和转换之间的区别。

public static void ExplicitTypeConversion2()
    {
        long longValue=long.MaxValue;
        float floatValue = float.MaxValue;
        int integerValue = (int) longValue;
        int integerValue2 = (int)floatValue;
        Console.WriteLine(integerValue);
        Console.WriteLine(integerValue2);            
    }

当我运行那段代码时,它输出:

当我运行该代码块时,输出如下:

-1
-2147483648

我知道如果你想给一个整数赋的值比它所能保存的要大,它会返回整数的最小值(-2147483648)。

据我所知,long.MaxValue 比一个整数的最大值要大得多,但是如果我将 long.MaxValue 强制转换为 int,它会返回 -1。

这两种强制转换有什么区别?我认为第一种强制转换也应该返回 -2147483648 而不是 -1。


1
我在思考另一个问题....int i = (int)long.MaxValue可以将i填充为0xFFFFFFFF,即-1,这对我来说很清楚。但是我想知道为什么int i = (int)float.MaxValue最终会落在int.MinValue,即0x80000000 - René Vogt
3个回答

16
如果要将一个大于整数可保持的值分配给整数,则返回整数的最小值。这不是规则。相关规则是在unchecked上下文中的整数类型:如果源类型大于目标类型,则通过丢弃其“额外”的最高有效位来截断源值。然后将结果视为目标类型的值。在unchecked上下文中的float->int:该值向零舍入为最近的整数值。如果此整数值在目标类型范围内,则该值是转换的结果。否则,转换的结果是目标类型的未指定值。从0x7fffffffffffffff去掉32个前导位得到0xffffffff,又称为-1。
你从未被承诺在将范围外的浮点数转换为整数时会获得 int.MinValue ,但你仍然会得到它,因为它很容易实现:x64 的转换指令 cvtss2si 会使得范围外的结果变为 0x80000000,类似地,fistp(32位 JIT 使用的旧 x87 转换指令)会存储“整数不确定值”,即 0x80000000。

在C#中,强制类型转换是基于十六进制格式0x7fffffffffffffff还是二进制进行的?我的意思是,例如从一种类型转换为另一种类型,如果我将其值转换为二进制以检查其他类型的位数,则决定是否可以保留或丢失数据。 - Tuncaf
@Tuncaf 在幕后没有格式。十六进制和二进制只是两种同样好的可视化方式,以展示正在发生的事情(但十六进制更短,这是我选择它的唯一原因)。 - harold

6
long.MaxValue的二进制值是0111...111111(以0开头,后面接63个1)。当你将其强制转换为int时,你会保留最低的32位111...11111。在十进制中,这等于-1,因为int是有符号的,采用二进制补码表示法。

在十进制中,它应该是“4294967295”,但由于Int32的最大值为2147483647,当达到此数字时,它会从-2147483648(其最小值)开始计数,然后确实达到-1。 - Paul Weiland
@PaulWeiland 不是的。如果是 unsigned,那么值将会是 4294967295。但是由于 int 是有符号的,32个1组成的序列在二进制补码中等于 -1 - AhmadWabbi

3
让我解释一下:
long longValue=long.MaxValue;
float floatValue = float.MaxValue;
int integerValue = (int) longValue;
int integerValue2 = (int)floatValue;
long类型的最大值为9,223,372,036,854,775,807或0x7FFFFFFFFFFFFFFF,在将其转换为0xFFFFFFFF后,使用2的补数表示,带有减号位,以十进制表示为-1。
另一方面,float类型的最大值为3.40282347E+38,因此将其强制转换为int会将值舍入为3E + 38,并在减小它后使用2的补数,我们得到具有减号位的十六进制值0x80000000,即在十进制中为-2147483648。
所有这些情况都适用于有符号整数,在无符号整数上结果将不同。
参考:https://msdn.microsoft.com/en-us/library/system.int64.maxvalue(v=vs.110).aspxhttps://msdn.microsoft.com/en-us/library/system.single.maxvalue(v=vs.110).aspx

你关于从浮点数转换为整数的论点是不正确的。你的说法“3.40282347E+38,因此将其强制转换为整数会将值舍入为3E + 38”只在纸和笔上是正确的,而不是在计算机上。 - AhmadWabbi
我不明白为什么这个答案被标记为已接受!它既不准确也不清晰。我认为@harlod的答案,目前已经获得了13票,应该被标记为已接受,而不是这个... - AhmadWabbi
从 https://msdn.microsoft.com/en-us/library/yht2cx7b.aspx 的第三条备注中可以看出:当您将 double 或 float 值转换为整数类型时,该值会被截断 [即取最近可能的值]。如果结果整数值超出目标值的范围,则结果取决于溢出检查上下文。这就是为什么显式数字转换会将 Single.MinValue 静默地转换为 Int32.MinValue 而不抛出 OverflowException 的原因。 - Tetsuya Yamamoto
@harold,好的...不知道那个!谢谢你的澄清。 - João Rebelo
@TetsuyaYamamoto 3E+38是如何被缩减为0x80000000的? - AhmadWabbi
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接