Чи можу я перетворити long в Int?


Відповіді:


218

Просто роби (int)myLongValue. Він зробить саме те, що ви хочете (відмови від MSB та прийняття LSB) у uncheckedконтексті (що є типовим для компілятора). Він буде кинутий OverflowExceptionу checkedконтекст, якщо значення не вписується у int:

int myIntValue = unchecked((int)myLongValue);

15
Для всіх, хто мав те саме запитання, що і я: Зауважте, що відмова від MSB може вплинути на ознаку результату. З вищезазначеним myIntValueможе закінчитися негативним, коли myLongValueє позитивним ( 4294967294 => -2) і навпаки ( -4294967296 => 0). Отже, реалізуючи CompareToоперацію, наприклад, ви не можете радісно передавати результат віднімання одного longвід іншого до intі повертати це; для деяких значень ваше порівняння дасть неправильний результат.
TJ Crowder

21
@Chris: new Random()використовує Environment.TickCountпід кришкою; не потрібно сіяти вручну за допомогою годинникових кліщів.
Мехрдад Афшарі

@MehrdadAfshari це було завжди?
Кріс Марісіч

3
Незважаючи на те, що це було років тому, причиною того, що я використовував це в новому Random, було те, що я отримував такі ж точні результати в одиничному тесті, і я хотів варіації. Використання числа дало мені дисперсію.
Кріс Марісіч

3
Контекст за замовчуванням є unchecked, тому якщо ви явно не змінили його, uncheckedключове слово (як показано у цій відповіді та коментарі @ ChrisMarisic тощо) не потрібне і int myIntValue = (int)myLongValueє рівнозначним. Однак зауважте, що незалежно від того, використовуєте ви uncheckedключове слово чи ні, ви отримуєте нематематичну грубу поведінку усічення, описану @TJCrowder, де знак може перевертатись у деяких випадках переповнення. Єдиний спосіб по-справжньому забезпечити математичну правильність - це використовувати checked(...)контекст, де ці випадки будуть винятком.
Гленн Слейден

35
Convert.ToInt32(myValue);

Хоча я не знаю, що це зробить, коли це більше, ніж int.MaxValue.


42
"Хоча я не знаю, що він буде робити, коли це більше, ніж int.MaxValue", це призведе до того OverflowException, що саме ОП не хоче: msdn.microsoft.com/en-us/library/d4haekc4.aspx
TJ Crowder

4
Перевірте, чи є myValue> Integer.Max перед запуском перетворення, якщо вам потрібно виконати іншу обробку, коли myValue> Integer.Max. Convert.ToInt32 (myValue) переповниться (не виняток, я вважаю) інакше. Цей метод працює і в VB.NET.
TamusJRoyce

3
Хоча (int) є дійсним, конвертувати - це краща відповідь. Краще мати дивні винятки, ніж дивні дані.
Річард Червень

1
@RichardJune Гм, ні? ОП тут прямо говорить: " Якщо значення long> int.MaxValue, я радий дозволити йому обернутися ". Я можу бачити аргументацію вашої заяви в цілому, але в цьому конкретному випадку ні, Convertце не добре.
ruffin

if (value > Int32.MaxValue) return Int32.MaxValue; else return Convert.ToInt32( value );
Сергій

15

Іноді вас насправді не цікавить фактичне значення, а його використання як контрольної суми / хеш-коду . У цьому випадку вбудований метод GetHashCode()- хороший вибір:

int checkSumAsInt32 = checkSumAsIn64.GetHashCode();

7
Минуло давно цю відповідь, хоча хочу зазначити, що реалізація хеш-коду може відрізнятися між версіями .NET. Це може насправді не відбуватися, але немає гарантії того, що це значення однакове між різними запусками / додатками додатків.
Караміріель

1
Щоб додати те, що говорить @Caramiriel: якщо ви використовуєте в якості тимчасового хеш-коду під час свого поточного сеансу програми, то GetHashCodeце відповідний вибір. Якщо ви перебуваєте після постійної контрольної суми - значення, яке буде таким самим, коли ви запускаєте додаток пізніше, тоді не використовуйте GetHashCode, оскільки не гарантується, що він буде завжди тим самим алгоритмом.
ToolmakerSteve

9

Найбезпечнішим і швидким способом є використання біт-маскування перед викликом ...

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

Значення Bit Mask ( 0xFFFFFFFF) буде залежати від розміру Int, оскільки розмір Int залежить від машини.


Потрібно вирішити, що ви хочете статися, коли результат або переповниться, або стане негативним числом. Те, що ви показуєте, все ще переповниться, IIRC, тому що ви пропускаєте знак трохи наскрізь. [Як було сказано в іншій відповіді, в uncheckedконтексті ви не отримаєте переповнення, але вам не потрібно маскуватися, uncheckedщоб уникнути переповнення, тому рішення потрібно лише в checkedконтексті.] Приклад для 16-біт. Підписано 16-бітові затримки (-32768, 32767). Маскування за допомогою 0xFFFF дозволяє отримати значення до 65535, викликаючи переповнення, IIRC. Не вдалося замаскувати, щоб уникнути бітових знаків, 0x7FFF або 0x7FFFFFFF, якщо потрібно лише позитив.
ToolmakerSteve

1

Він може конвертувати

Метод 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.

Тут є більш тривале пояснення.


0

Не став би

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

бути правильним, математично кажучи?


Це затиснутиlongValue до найближчого представимо , intякщо початкове значення є величезним. Але йому не вистачає такої ж трактування надто негативних входів, які б втратили найзначніші біти; вам також доведеться порівнювати Int32.MinValue. Очевидний плакат, здається, не хотів затискати.
Jeppe Stig Nielsen

ІМХО іноді краще отримати виняток, ніж неправильне значення, яке Int32.MaxValue було б ...
Г. Гончаров

0

Наступне рішення буде скорочено до int.MinValue / int.MaxValue, якщо значення виходить за межі Цілого числа.

myLong < int.MinValue ? int.MinValue : (myLong > int.MaxValue ? int.MaxValue : (int)myLong)

0

Можливий спосіб - використовувати оператор модуля, щоб лише дати значенням залишитися в діапазоні int32, а потім передати їх на int.

var intValue= (int)(longValue % Int32.MaxValue);
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.