Bisakah saya mengonversi panjang menjadi int?

142

Saya ingin mengonversi longke int.

Jika nilai long> int.MaxValue, saya senang membiarkannya membungkus.

Apakah cara terbaiknya?

meskipun
sumber

Jawaban:

218

Lakukan saja (int)myLongValue. Ini akan melakukan apa yang Anda inginkan (membuang MSB dan mengambil LSB) dalam uncheckedkonteks (yang merupakan kompiler default). Ini akan melempar OverflowExceptiondalam checkedkonteks jika nilainya tidak cocok dengan int:

int myIntValue = unchecked((int)myLongValue);
Mehrdad Afshari
sumber
15
Untuk siapa pun yang memiliki pertanyaan yang sama saya lakukan: Perhatikan bahwa membuang MSB dapat memiliki efek pada tanda hasil. Dengan hal di atas, myIntValuebisa berakhir negatif ketika myLongValuepositif ( 4294967294 => -2) dan sebaliknya ( -4294967296 => 0). Jadi, ketika mengimplementasikan CompareTooperasi, misalnya, Anda tidak bisa dengan senang hati menyerahkan hasil dari mengurangi satu longdari yang lain ke intdan mengembalikannya; untuk beberapa nilai, perbandingan Anda akan menghasilkan hasil yang salah.
TJ Crowder
21
@ Chris: new Random()gunakan di Environment.TickCountbawah tenda; tidak perlu seed secara manual dengan tick tick.
Mehrdad Afshari
@MehrdadAfshari selalu seperti itu?
Chris Marisic
3
Meskipun ini bertahun-tahun yang lalu, alasan saya menggunakannya dalam Random baru adalah bahwa saya mendapatkan hasil yang persis sama dalam tes unit dan saya ingin varians. Menggunakan nomor itu memberi saya perbedaan.
Chris Marisic
3
Konteks defaultnya adalah unchecked, jadi kecuali Anda telah mengubahnya secara eksplisit, maka uncheckedkata kunci (seperti yang ditunjukkan dalam jawaban ini dan komentar @ ChrisMarisic, dll.) Tidak diperlukan, dan int myIntValue = (int)myLongValuesama persis. Namun perlu dicatat bahwa terlepas dari apakah Anda menggunakan uncheckedkata kunci atau tidak, Anda mendapatkan perilaku pemotongan kasar non-matematis yang dijelaskan oleh @TJCrowder di mana tanda dapat membalik dalam beberapa kasus overflow. Satu-satunya cara untuk benar-benar memastikan kebenaran matematis adalah dengan menggunakan checked(...)konteks, di mana kasus-kasus tersebut akan memberikan pengecualian.
Glenn Slayden
35
Convert.ToInt32(myValue);

Meskipun saya tidak tahu apa yang akan dilakukan ketika lebih besar dari int.MaxValue.

Max Schmeling
sumber
42
"Meskipun saya tidak tahu apa yang akan dilakukan ketika lebih besar dari int.MaxValue" Ini akan melempar OverflowException, yang persis apa yang tidak diinginkan OP: msdn.microsoft.com/en-us/library/d4haekc4.aspx
TJ Crowder
4
Uji apakah myValue> Integer.Max sebelum menjalankan konversi, jika Anda perlu melakukan pemrosesan lain ketika myValue> Integer.Max. Convert.ToInt32 (myValue) akan melimpah (tidak terkecuali, saya percaya) sebaliknya. Metode ini juga berfungsi di VB.NET.
TamusJRoyce
3
Sementara (int) valid, Konversi adalah jawaban yang lebih baik. Lebih baik memiliki pengecualian aneh daripada data aneh.
Richard
1
@ Richard Um, Um, tidak? OP di sini secara eksplisit mengatakan, " Jika nilai long> int.MaxValue, saya senang membiarkannya membungkus. " Saya bisa melihat argumen pernyataan Anda secara umum, tetapi dalam kasus khusus ini , tidak, Converttidak baik.
ruffin
if (value > Int32.MaxValue) return Int32.MaxValue; else return Convert.ToInt32( value );
Sergey
15

Terkadang Anda sebenarnya tidak tertarik dengan nilai aktual, tetapi dalam penggunaannya sebagai checksum / kode hash . Dalam hal ini, metode bawaan GetHashCode()adalah pilihan yang baik:

int checkSumAsInt32 = checkSumAsIn64.GetHashCode();
realbart
sumber
7
Sudah lama sejak jawaban ini diberikan, meskipun saya ingin menyebutkan bahwa implementasi kode hash mungkin berbeda antara versi .NET. Ini mungkin tidak benar-benar terjadi, tetapi tidak ada jaminan bahwa nilai ini sama antara menjalankan aplikasi / appdomain yang berbeda.
Caramiriel
1
Untuk menambahkan apa yang dikatakan @Caramiriel: jika menggunakan kode hash sementara , selama sesi aplikasi Anda saat ini, maka itu GetHashCodeadalah pilihan yang tepat. Jika Anda mencari checksum yang persisten - nilai yang akan sama ketika Anda menjalankan aplikasi nanti, maka jangan gunakan GetHashCode, karena itu tidak dijamin akan menjadi algoritma yang sama selamanya.
ToolmakerSteve
9

Cara aman dan tercepat adalah menggunakan Bit Masking sebelum ...

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

Nilai Bit Mask ( 0xFFFFFFFF) akan tergantung pada ukuran Int karena ukuran Int tergantung pada mesin.

Mashake
sumber
Perlu memutuskan apa yang Anda inginkan terjadi ketika hasilnya akan meluap, atau menjadi angka negatif. Apa yang Anda tunjukkan masih akan meluap, IIRC, karena Anda membiarkan tandanya melewati. [Seperti yang disebutkan dalam jawaban lain, dalam uncheckedkonteks Anda tidak akan mendapatkan overflow - tetapi Anda tidak perlu menutupi uncheckeduntuk menghindari overflow, jadi solusi hanya diperlukan dalam checkedkonteks.] Contoh untuk 16-bit. Ditandatangani penahan 16-bit (-32768, 32767). Masking dengan 0xFFFF memungkinkan nilai hingga 65535, menyebabkan overflow, IIRC. Dapat menutupi untuk menghindari bit tanda, 0x7FFF atau 0x7FFFFFFF, jika ingin positif saja.
ToolmakerSteve
1

Itu dapat dikonversi oleh

Metode Convert.ToInt32

Tapi itu akan melempar OverflowException jika nilainya di luar kisaran Tipe Int32. Tes dasar akan menunjukkan kepada kita cara kerjanya:

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.

Di sini ada penjelasan yang lebih panjang.

nzrytmn
sumber
0

Tidak akan

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

menjadi cara yang benar, secara matematis?

Remy Esmery
sumber
Hal ini akan menjepit yang longValueke representable terdekat intjika nilai asli untuk besar. Tetapi tidak memiliki perlakuan yang sama dari input yang terlalu negatif, yang akan kehilangan bit paling signifikan sebagai gantinya; Anda perlu membandingkan Int32.MinValuejuga. Namun, poster aslinya sepertinya tidak ingin dijepit.
Jeppe Stig Nielsen
IMHO kadang-kadang lebih baik untuk mendapatkan pengecualian daripada nilai yang salah, yang Int32.MaxValue akan menjadi ...
G. Goncharov
0

Solusi berikut akan memotong ke int.MinValue / int.MaxValue jika nilainya di luar batas Integer.

myLong < int.MinValue ? int.MinValue : (myLong > int.MaxValue ? int.MaxValue : (int)myLong)
Sejuk
sumber
0

Cara yang mungkin adalah dengan menggunakan operator modulo untuk hanya membiarkan nilai tetap dalam kisaran int32, dan kemudian melemparkannya ke int.

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