我能把long转换为int吗?

172

我想将long转换为int

如果long的值 > int.MaxValue, 我希望它可以循环回来。

最好的方式是什么?

8个回答

248

只需执行(int)myLongValue即可。在unchecked上下文中(这是编译器默认设置),它将完全按照您的要求执行(丢弃MSB并获取LSB)。如果该值不适合int,则在checked上下文中会抛出OverflowException异常:

int myIntValue = unchecked((int)myLongValue);

18
如果有其他人和我一样有这个问题:请注意,舍弃最高位可能会对结果的符号产生影响。使用上述方法,当myLongValue为正数时(4294967294 => -2),myIntValue可能会变成负数,反之亦然(-4294967296 => 0)。因此,在实现CompareTo操作时,你不能将一个long减去另一个强制转换为int并返回;对于某些值,你的比较将产生错误的结果。 - T.J. Crowder
23
@Chris说:new Random()在内部使用Environment.TickCount,不需要手动使用时钟滴答进行种子初始化。 - Mehrdad Afshari
4
默认情况下上下文是“未检查”,所以除非您已经明确更改了它,否则不需要使用“未检查”关键字(如此答案和@ChrisMarisic的注释等)。在这种情况下,“int myIntValue = (int)myLongValue”与其完全等效。但请注意,无论您是否使用“未检查”关键字,都将获得由@T.J.Crowder描述的非数学粗鲁截断行为,在某些溢出情况下符号可能会翻转。确保数学正确性的唯一方法是使用“checked(...)”上下文,这些情况将抛出异常。 - Glenn Slayden

46
Convert.ToInt32(myValue);

虽然我不知道当它大于int.MaxValue时会发生什么。


55
如果大于 int.MaxValue,它将抛出一个 OverflowException 异常,这正是 OP 不想发生的:http://msdn.microsoft.com/en-us/library/d4haekc4.aspx - T.J. Crowder
5
在进行转换之前,测试myValue是否大于Integer.Max,如果需要在myValue大于Integer.Max时进行其他处理。否则Convert.ToInt32(myValue)将会溢出(我相信不会抛出异常)。这种方法在VB.NET中同样适用。 - TamusJRoyce
3
当使用(int)时,Convert是更好的选择。有奇怪的异常总比有奇怪的数据好。 - Richard June
1
@RichardJune 嗯,不是吧?这里的OP明确表示,“如果long的值> int.MaxValue,我很高兴让它绕过来”。我可以看出你在一般情况下争辩你的陈述,但在这个特定情况下,Convert不好。 - ruffin
if (value > Int32.MaxValue) return Int32.MaxValue; else return Convert.ToInt32( value ); - Sergey
@Sergey - 如果这是你想要做的事情,那么不要忘记负数:return value < Int32.MinValue ? Int32.MinValue : (value > Int32.MaxValue ? Int32.MaxValue : (int)value); - ToolmakerSteve

17
有时候你并不关心实际值,而是关心它作为校验和/哈希码的用途。在这种情况下,内置方法GetHashCode() 是一个不错的选择:
int checkSumAsInt32 = checkSumAsIn64.GetHashCode();

8
虽然这个答案是一段时间前给出的,但我想提醒一下,hashcode的实现在不同的.NET版本中可能会有所不同。虽然这种情况可能并不会发生,但不能保证在不同的应用程序运行或应用程序域之间此值相同。 - Caramiriel
1
补充一下 @Caramiriel 的说法:如果在当前应用程序会话期间使用作为临时哈希码,则 GetHashCode 是一个合适的选择。如果您想要一个持久的校验和 - 一个在以后运行应用程序时将保持相同的值,则不要使用 GetHashCode,因为它不能保证永远使用相同的算法。 - ToolmakerSteve

12

最安全和最快的方法是在强制类型转换之前使用位掩码...

int MyInt = (int) ( MyLong & 0xFFFFFFFF )

位掩码(0xFFFFFFFF)的值取决于Int的大小,因为Int的大小取决于机器。


1
需要决定当结果溢出或变为负数时想要发生什么。如果您让符号位通过,那么显示的内容仍将溢出,如另一个答案中所述,在“unchecked”上下文中,您不会遇到溢出-但是您不需要在“unchecked”中进行掩码以避免溢出,因此只需要在“checked”上下文中提供解决方案。例如16位。有符号16位保持(-32768,32767)。使用0xFFFF进行掩码允许值高达65535,导致溢出,如另一个答案中所述,如果只想要正数,则可以使用0x7FFF或0x7FFFFFFF进行掩码。 - ToolmakerSteve

12

一种可能的方法是使用模运算符仅让值保留在int32范围内,然后将其转换为int。

var intValue= (int)(longValue % Int32.MaxValue);

这对我来说效果最好,因为所有其他位掩码尝试都会将281474976710656(2^48)转换为0。 - GuiRitter
2
@GuiRitter - 某些大值仍将变为0(MaxValue的任何倍数)。相反,考虑使用(int)(longValue > Int32.MaxValue ? (longValue % Int32.MaxValue) + 1 : longValue)。类似的逻辑也可以用于负值:(int)(longValue < Int32.MinValue ? (longValue % Int32.MaxValue) - 1 ? (longValue > Int32.MaxValue ? (longValue % Int32.MaxValue) + 1 : longValue)) - ToolmakerSteve
@ToolmakerSteve 没有避免零的要求。实际上,“环绕”似乎表明零是可以接受的。 - Mike Burton
@MikeBurton - 你是正确的,关于原始问题。我是在回应GuiRitter,他似乎想要一个不将任何值转换为0的解决方案。既然他们喜欢这个,我想他们想要的是对于大于0的值保持在0以上的东西。顺便说一下,我赞成被接受的答案,以及realbart和Clement的答案。在我看来,它们涵盖了转换为int的三种最常见用法。 - ToolmakerSteve

5
如果值超出Integer的范围,下面的解决方案将截断为int.MinValue/int.MaxValue。
myLong < int.MinValue ? int.MinValue : (myLong > int.MaxValue ? int.MaxValue : (int)myLong)

3
它可以通过 Convert.ToInt32 方法进行转换,但如果值超出 Int32 类型的范围,它会抛出 OverflowException 异常。 一个基本测试将展示它的工作原理:
long[] numbers = { Int64.MinValue, -1, 0, 121, 340, Int64.MaxValue };
int result;
foreach (long number in numbers)
{
   try {
         result = Convert.ToInt32(number);
        Console.WriteLine("Converted the {0} value {1} to the {2} value {3}.",
                    number.GetType().Name, number,
                    result.GetType().Name, result);
     }
     catch (OverflowException) {
      Console.WriteLine("The {0} value {1} is outside the range of the Int32 type.",
                    number.GetType().Name, number);
     }
}
// The example displays the following output:
//    The Int64 value -9223372036854775808 is outside the range of the Int32 type.
//    Converted the Int64 value -1 to the Int32 value -1.
//    Converted the Int64 value 0 to the Int32 value 0.
//    Converted the Int64 value 121 to the Int32 value 121.
//    Converted the Int64 value 340 to the Int32 value 340.
//    The Int64 value 9223372036854775807 is outside the range of the Int32 type.

这里有更详细的解释。


2

Wouldn't

(int) Math.Min(Int32.MaxValue, longValue)

最初的回答可能在数学上是正确的,但是否是最佳方式呢?

如果原始值太大,这将把 longValue 夹紧到最接近的可表示 int。但它缺乏对于过于负面的输入的相同处理,这将导致最高有效位丢失;您还需要与 Int32.MinValue 进行比较。然而,原帖似乎并不想要夹紧。 - Jeppe Stig Nielsen
在我看来,有时候抛出异常比返回错误的值更好,而 Int32.MaxValue 就是这样的一个例子... - G. Goncharov
要同时夹紧负值,请使用(int)Math.Max(Int32.MinValue, Math.Min(Int32.MaxValue, longValue))。然而,我发现等效的 https://dev59.com/CXRA5IYBdhLWcg3wsgPq#58011064 更容易理解。 - ToolmakerSteve

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