Я хочу преобразовать long
в int
.
Если значение long
> int.MaxValue
, я с радостью позволю ему обернуться.
Как лучше всего?
Ответы:
Просто сделай (int)myLongValue
. Он будет делать именно то, что вы хотите (отбрасывая MSB и принимая LSB) в unchecked
контексте (который является компилятором по умолчанию). Он будет вставлен OverflowException
в checked
контекст, если значение не соответствует int
:
int myIntValue = unchecked((int)myLongValue);
new Random()
использует Environment.TickCount
под капотом; нет необходимости засеивать вручную по тикам часов.
unchecked
, поэтому, если вы явно не изменили его, unchecked
ключевое слово (как показано в этом ответе и комментарии @CrisMarisic и т. Д.) Не требуется и int myIntValue = (int)myLongValue
полностью эквивалентно. Однако обратите внимание, что независимо от того, используете ли вы unchecked
ключевое слово или нет, вы получаете нематематическое грубое усечение, описанное @TJCrowder, когда знак может перевернуться в некоторых случаях переполнения. Единственный способ по-настоящему гарантировать математическую корректность - использовать checked(...)
контекст, в котором эти случаи вызовут исключение.
Convert.ToInt32(myValue);
Хотя я не знаю, что он будет делать, если он больше int.MaxValue.
OverflowException
, а это именно то, чего OP не хочет: msdn.microsoft.com/en-us/library/d4haekc4.aspx
Convert
это нехорошо.
if (value > Int32.MaxValue)
return Int32.MaxValue;
else
return Convert.ToInt32( value );
Иногда вас действительно интересует не фактическое значение, а его использование в качестве контрольной суммы / хэш-кода . В этом случае GetHashCode()
хорошим выбором будет встроенный метод :
int checkSumAsInt32 = checkSumAsIn64.GetHashCode();
GetHashCode
это подходящий выбор. Если вам нужна постоянная контрольная сумма - значение, которое будет таким же, когда вы запустите приложение позже, то не используйте GetHashCode
, поскольку не гарантируется, что это будет один и тот же алгоритм навсегда.
Самый безопасный и быстрый способ - использовать Bit Masking перед кастом ...
int MyInt = (int) ( MyLong & 0xFFFFFFFF )
Значение Bit Mask ( 0xFFFFFFFF
) будет зависеть от размера Int, потому что размер Int зависит от машины.
unchecked
контексте вы не получите переполнения, но вам не нужно маскироваться, unchecked
чтобы избежать переполнения, поэтому решение требуется только в checked
контексте.] Пример для 16-бит. 16-битные со знаком (-32768, 32767). Маскирование с помощью 0xFFFF допускает значение до 65535, вызывая переполнение IIRC. Может маскировать, чтобы избежать бит знака, 0x7FFF или 0x7FFFFFFF, если нужен только положительный результат.
Возможный способ - использовать оператор по модулю, чтобы значения оставались только в диапазоне int32, а затем преобразовать его в int.
var intValue= (int)(longValue % Int32.MaxValue);
Он может конвертировать
Convert.ToInt32 метод
Но он вызовет исключение OverflowException, если значение выходит за пределы диапазона типа Int32. Базовый тест покажет нам, как это работает:
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.
Здесь есть более подробное объяснение.
Не стал бы
(int) Math.Min(Int32.MaxValue, longValue)
быть правильным, математически говоря?
longValue
до ближайшего представимого , int
если исходное значение является огромным. Но ему не хватает такой же обработки слишком отрицательных входных данных, которые вместо этого потеряли бы наиболее значимые биты; вам также нужно будет сравнить Int32.MinValue
. Однако исходный плакат, похоже, не нуждался в зажимах.
myIntValue
может оказаться отрицательным, когдаmyLongValue
положительно (4294967294 => -2
), и наоборот (-4294967296 => 0
). ТакCompareTo
, например, при реализации операции вы не можете успешноlong
преобразовать результат вычитания одного из другогоint
и вернуть его; для некоторых значений сравнение даст неверный результат.