Uzun bir int dönüştürmek miyim?


142

Ben dönüştürmek istiyorum longiçin int.

Eğer değeri long> ise int.MaxValue, etrafı sarmasına izin vermekten mutluluk duyarım.

En iyi yol nedir?

Yanıtlar:


218

Sadece yap (int)myLongValue. Tam olarak istediğinizi yapar (MSB'leri atar ve LSB'leri alır) uncheckedbağlamda (derleyici varsayılanıdır). Değer aşağıdakilere uymuyorsa bağlam OverflowExceptioniçinde atar :checkedint

int myIntValue = unchecked((int)myLongValue);

15
Aynı soruya sahip olan herkes için yaptım: MSB'leri atmanın sonucun işareti üzerinde bir etkisi olabilir . Yukarıdakilerle, pozitif ( ) ve tersi ( ) myIntValueolduğunda negatif sonuçlanabilir . Örneğin, bir işlemi uygularken , birinden diğerinden çıkarmanın sonucunu mutlu bir şekilde çıkaramazsınız ve bunu döndüremezsiniz; bazı değerler için karşılaştırmanız yanlış bir sonuç verir. myLongValue4294967294 => -2-4294967296 => 0CompareTolongint
TJ Crowder

21
@Chris: kaputun altında new Random()kullanır Environment.TickCount; saat keneleri ile elle tohumlamaya gerek yok.
Mehrdad Afshari

@MehrdadAfshari hep böyle oldu mu?
Chris Marisic

3
Bu yıllar önce olmasına rağmen, yeni Rastgele kullanmamın nedeni, bir birim testinde aynı sonuçları elde etmekti ve varyans istedim. Numarayı kullanmak bana sapma verdi.
Chris Marisic

3
Varsayılan bağlam unchecked, bu nedenle, açıkça değiştirmedikçe, uncheckedanahtar kelimeye (bu cevapta ve @ ChrisMarisic'in yorumunda gösterildiği gibi) gerek yoktur ve int myIntValue = (int)myLongValuetam olarak eşdeğerdir. Ancak, uncheckedanahtar kelimeyi kullanıp kullanmadığınıza bakılmaksızın, @TJCrowder tarafından tanımlanan ve işaretin bazı taşma durumlarında dönebileceği matematiksel olmayan kaba kesme davranışını elde ettiğinizi unutmayın. Matematiksel doğruluğu gerçekten sağlamanın tek yolu checked(...), bu durumların bir istisna oluşturacağı bağlamı kullanmaktır .
Glenn Slayden

35
Convert.ToInt32(myValue);

Rağmen int.MaxValue büyük olduğunda ne yapacağını bilmiyorum.


42
"İnt.MaxValue daha büyük olduğunda ne yapacağını bilmiyorum rağmen" Bir OverflowExceptionOP atacak tam olarak ne atar : msdn.microsoft.com/en-us/library/d4haekc4.aspx
TJ Crowder

4
Dönüştürmeyi çalıştırmadan önce myValue> Integer.Max'ın, myValue> Integer.Max olduğunda başka işlemler yapmanız gerekip gerekmediğini test edin. Convert.ToInt32 (myValue) taşacak (istisna yok, inanıyorum) aksi takdirde. Bu yöntem VB.NET'te de çalışır.
TamusJRoyce

3
(İnt) geçerli olsa da, Convert daha iyi bir yanıttır. Tuhaf verilerden daha tuhaf istisnalara sahip olmak daha iyidir.
Richard Haziran

1
@RichardJune Um, hayır? Burada OP açıkça , " Eğer long> int.MaxValue değeri, onu sarmak için mutluyum " diyor . Genel olarak ifade savunarak görebilirsiniz, ama bu özel durumda , hayır, Convertiyi değil.
ruffin

if (value > Int32.MaxValue) return Int32.MaxValue; else return Convert.ToInt32( value );
Sergey

15

Bazen gerçek değerle değil, checksum / hashcode olarak kullanılmasıyla ilgilenirsiniz . Bu durumda, yerleşik yöntem GetHashCode()iyi bir seçimdir:

int checkSumAsInt32 = checkSumAsIn64.GetHashCode();

7
Bu yanıt verildiğinden beri bir süre önce oldu, ancak hashcode uygulamasının .NET sürümleri arasında farklı olabileceğinden bahsetmek istiyorum. Bu aslında gerçekleşmeyebilir, ancak bu değerin farklı uygulama çalıştırmaları / uygulama alanları arasında aynı olduğuna dair bir garanti yoktur.
Caramiriel

1
@Caramiriel'in söylediklerine eklemek için: geçici bir karma kod olarak kullanılıyorsa , geçerli uygulama oturumunuz sırasında GetHashCodeuygun bir seçimdir. Eğer bir sonraki ise kalıcı sağlama - ilerde uygulamayı çalıştırdığınızda aynı olacaktır bir değere, o zaman kullanmayın GetHashCodesonsuza aynı algoritma olması garanti edilmez olarak.
ToolmakerSteve

9

Güvenli ve hızlı yol, yayınlamadan önce Bit Maskelemeyi kullanmaktır ...

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

Bit Maskesi ( 0xFFFFFFFF) değeri Int boyutuna bağlı olacaktır, çünkü Int boyutu makineye bağlıdır.


Sonuç taşacak veya negatif bir sayı olduğunda ne olmasını istediğinize karar vermeniz gerekir. Gösterdiğiniz şey hala taşacak, IIRC, çünkü işaretin bitmesine izin veriyorsunuz. [Başka bir cevapta belirtildiği gibi, uncheckedbağlamda bir taşma olmaz - ancak uncheckedtaşmayı önlemek için maskelenmeniz gerekmez , bu nedenle sadece checkedbağlamda bir çözüme ihtiyaç vardır .] 16 bitlik örnek. İşaretli 16 bitlik ambarlar (-32768, 32767). 0xFFFF ile maskeleme, 65535'e kadar değere izin vererek taşmaya, IIRC'ye neden olur. Yalnızca pozitif istiyorsanız işaret biti, 0x7FFF veya 0x7FFFFFFF önlemek için maske olabilir.
ToolmakerSteve

1

Tarafından dönüştürebilirsiniz

Convert.ToInt32 yöntemi

Ancak, değer Int32 Türünün aralığının dışındaysa bir OverflowException özel durumu atar. Temel bir test bize nasıl çalıştığını gösterecektir:

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.

Burada daha uzun bir açıklama var.


0

değil mi

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

matematiksel olarak doğru bir yol olabilir mi?


Bu olur kelepçelongValue yakın ifade edilebilen intorijinal değer büyük yollarından biri. Ancak, bunun yerine en önemli bitleri kaybedecek olan çok olumsuz girdilerin aynı muamelesinden yoksundur; karşılaştırmak gerekir Int32.MinValue. Yine de orijinal poster sıkmak istemiyordu.
Jeppe Stig Nielsen

IMHO bazen Int32.MaxValue olurdu yanlış değerden istisna almak için daha iyi ...
G. Goncharov

0

Değer Tamsayı sınırları dışındaysa, aşağıdaki çözüm int.MinValue / int.MaxValue olarak kesilir.

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

0

Olası bir yol, modulo operatörünü yalnızca değerlerin int32 aralığında kalmasına izin vermek ve daha sonra int'e atmaktır.

var intValue= (int)(longValue % Int32.MaxValue);
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.