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?
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);
Convert.ToInt32(myValue);
Though I don't know what it will do when it's greater than int.MaxValue.
OverflowException
, which is exactly what the OP doesn't want: msdn.microsoft.com/en-us/library/d4haekc4.aspx
Convert
is not good.
if (value > Int32.MaxValue)
return Int32.MaxValue;
else
return Convert.ToInt32( value );
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();
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.
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.
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.
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);
(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))
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)
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.
Wouldn't
(int) Math.Min(Int32.MaxValue, longValue)
be the correct way, mathematically speaking?
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.
(int)Math.Max(Int32.MinValue, Math.Min(Int32.MaxValue, longValue))
. However I find the equivalent stackoverflow.com/a/58011064/199364 easier to understand.
Success story sharing
myIntValue
can end up negative whenmyLongValue
is positive (4294967294 => -2
) and vice-versa (-4294967296 => 0
). So when implementing aCompareTo
operation, for instance, you can't happily cast the result of subtracting onelong
from another to anint
and return that; for some values, your comparison would yield an incorrect result.new Random()
usesEnvironment.TickCount
under the hood; no need to seed manually with clock ticks.unchecked
, so unless you've explicitly changed it, then theunchecked
keyword (as shown in this answer and @ChrisMarisic's comment, etc.) is not needed, andint myIntValue = (int)myLongValue
is exactly equivalent. However do note that regardless of whether you use theunchecked
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 thechecked(...)
context, where those cases will throw an exception.