171

I want to convert long to int.

If the value of long > int.MaxValue, I am happy to let it wrap around.

What is the best way?

Sergey Kulgan
  • 1,215
  • 1
  • 12
  • 12
Ian G
  • 29,468
  • 21
  • 78
  • 92

8 Answers8

245

Just do (int)myLongValue. It'll do exactly what you want (discarding MSBs and taking LSBs) in unchecked context (which is the compiler default). It'll throw OverflowException in checked context if the value doesn't fit in an int:

int myIntValue = unchecked((int)myLongValue);
Mehrdad Afshari
  • 414,610
  • 91
  • 852
  • 789
  • 18
    For anyone else who had the same question I did: Note that discarding the MSBs can have an effect on the *sign* of the result. With the above, `myIntValue` can end up negative when `myLongValue` is positive (`4294967294 => -2`) and vice-versa (`-4294967296 => 0`). So when implementing a `CompareTo` operation, for instance, you can't happily cast the result of subtracting one `long` from another to an `int` and return that; for some values, your comparison would yield an incorrect result. – T.J. Crowder Apr 10 '11 at 08:56
  • 23
    @Chris: `new Random()` uses `Environment.TickCount` under the hood; no need to seed manually with clock ticks. – Mehrdad Afshari Oct 08 '11 at 22:51
  • 4
    The default context is `unchecked`, so unless you've explicitly changed it, then the `unchecked` keyword (as shown in this answer and @ChrisMarisic's comment, etc.) is not needed, and `int myIntValue = (int)myLongValue` is exactly equivalent. However do note that regardless of whether you use the `unchecked` keyword or not, you're getting the non-mathematical rude truncation behavior described by @T.J.Crowder where the sign can flip in some overflow cases. The only way to truly ensure mathematical correctness is to use the `checked(...)` context, where those cases will throw an exception. – Glenn Slayden Feb 04 '17 at 05:36
46
Convert.ToInt32(myValue);

Though I don't know what it will do when it's greater than int.MaxValue.

Max Schmeling
  • 12,363
  • 14
  • 66
  • 109
  • 54
    *"Though I don't know what it will do when it's greater than int.MaxValue"* It will throw an `OverflowException`, which is exactly what the OP doesn't want: http://msdn.microsoft.com/en-us/library/d4haekc4.aspx – T.J. Crowder Apr 10 '11 at 08:44
  • 5
    Test if myValue > Integer.Max before running the convert, if you need to do other processing when myValue > Integer.Max. Convert.ToInt32(myValue) will overflow (no exception, I believe) otherwise. This method works in VB.NET as well. – TamusJRoyce Oct 06 '11 at 15:38
  • 3
    While (int) is valid, Convert is a better answer. Better to have weird exceptions than weird data. – Richard June Aug 11 '14 at 00:35
  • 1
    @RichardJune Um, no? The OP here *explicitly* says, "*If the value of long > int.MaxValue, I am happy to let it wrap around.*" I can see arguing your statement in general, but in *this specific case*, no, `Convert` is not good. – ruffin Mar 13 '17 at 15:08
  • `if (value > Int32.MaxValue)` `return Int32.MaxValue;` `else` `return Convert.ToInt32( value );` – Sergey Apr 03 '17 at 16:15
  • @Sergey - if that is what you want to do, then don't forget MINUS numbers: `return value < Int32.MinValue ? Int32.MinValue : (value > Int32.MaxValue ? Int32.MaxValue : (int)value);` – ToolmakerSteve Aug 03 '21 at 12:48
17

Sometimes you're not actually interested in the actual value, but in its usage as checksum/hashcode. In this case, the built-in method GetHashCode() is a good choice:

int checkSumAsInt32 = checkSumAsIn64.GetHashCode();
Omar
  • 16,329
  • 10
  • 48
  • 66
realbart
  • 3,497
  • 1
  • 25
  • 37
  • 8
    It's been a while ago since this answer was given, though I want to mention that the hashcode implementation might differ between .NET versions. This might not actually be happening, but there is no guarantee that this value is the same between different application runs/appdomains. – Caramiriel Mar 21 '14 at 09:29
  • 1
    To add to what @Caramiriel is saying: if using as a *temporary* hashcode, during your current app session, then `GetHashCode` is an appropriate choice. If you are after a *persistent checksum* - a value that will be the same when you run your app later, then don't use `GetHashCode`, as it is not guaranteed to be the same algorithm forever. – ToolmakerSteve Feb 28 '18 at 23:11
12

The safe and fastest way is to use Bit Masking before cast...

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

The Bit Mask ( 0xFFFFFFFF ) value will depend on the size of Int because Int size is dependent on machine.

Yu Hao
  • 119,891
  • 44
  • 235
  • 294
Mashake
  • 121
  • 1
  • 2
  • 1
    Need to decide what you want to happen when the result will either overflow, or become a negative number. What you show will still overflow, IIRC, because you are letting the sign bit through. [As mentioned in another answer, in `unchecked` context you won't get an overflow - but you don't need to mask in `unchecked` to avoid the overflow, so a solution is only needed in `checked` context.] Example for 16-bits. Signed 16-bits holds (-32768, 32767). Masking with 0xFFFF allows value up to 65535, causing overflow, IIRC. Could mask to avoid sign bit, 0x7FFF or 0x7FFFFFFF, if want positive only. – ToolmakerSteve Feb 28 '18 at 22:52
12

A possible way is to use the modulo operator to only let the values stay in the int32 range, and then cast it to int.

var intValue= (int)(longValue % Int32.MaxValue);
Andre
  • 326
  • 4
  • 12
  • This worked best for me, as all other attempts to bit mask transformed 281474976710656 (2^48) to 0. – GuiRitter Aug 26 '20 at 12:04
  • 2
    @GuiRitter - Certain large values will still become 0. (Any multiple of MaxValue). Consider instead `(int)(longValue > Int32.MaxValue ? (longValue % Int32.MaxValue) + 1 : longValue)`. Similar logic can be added for negative values: `(int)(longValue < Int32.MinValue ? (longValue % Int32.MaxValue) - 1 ? (longValue > Int32.MaxValue ? (longValue % Int32.MaxValue) + 1 : longValue))` – ToolmakerSteve Aug 03 '21 at 13:03
  • @ToolmakerSteve There's no requirement to avoid zeros. Indeed, "wrap around" would seem to indicate zeros are fine. – Mike Burton Jun 02 '23 at 15:40
  • @MikeBurton - You are correct, re the original question. I was responding to GuiRitter, who seemed to want a solution that did not convert any value to 0. Since they liked this one, I figured they wanted something that stayed above 0, for values above 0. FYI, I upvoted the accepted answer, as well as realbart's and Clement's answers. These cover the 3 most common usages of converting to int, imho. – ToolmakerSteve Jun 02 '23 at 18:54
5

The following solution will truncate to int.MinValue/int.MaxValue if the value is out of Integer bounds.

myLong < int.MinValue ? int.MinValue : (myLong > int.MaxValue ? int.MaxValue : (int)myLong)
Clement
  • 3,990
  • 4
  • 43
  • 44
3

It can convert by

Convert.ToInt32 method

But it will throw an OverflowException if it the value is outside range of the Int32 Type. A basic test will show us how it works:

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.

Here there is a longer explanation.

nzrytmn
  • 6,193
  • 1
  • 41
  • 38
2

Wouldn't

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

be the correct way, mathematically speaking?

Zoe
  • 27,060
  • 21
  • 118
  • 148
Rémy Esmery
  • 658
  • 6
  • 14
  • This would ___clamp___ the `longValue` to the nearest representable `int` if the original value is to huge. But it lacks the same treatment of too negative inputs, which would lose the most significant bits instead; you would need to compare to `Int32.MinValue` also. The original poster did not seem to want clamping, though. – Jeppe Stig Nielsen Mar 02 '19 at 11:02
  • IMHO sometimes better to get exception than wrong value, which Int32.MaxValue would be... – G. Goncharov Jan 20 '20 at 04:33
  • To clamp negative values also, do `(int)Math.Max(Int32.MinValue, Math.Min(Int32.MaxValue, longValue))`. However I find the equivalent https://stackoverflow.com/a/58011064/199364 easier to understand. – ToolmakerSteve Aug 03 '21 at 12:56