ฉันสามารถแปลงเป็น long ได้หรือไม่


142

ฉันต้องการที่จะแปลงไปlongint

หากค่าของlong> int.MaxValueฉันมีความสุขที่จะปล่อยให้มันล้อมรอบ

วิธีที่ดีที่สุดคืออะไร?

คำตอบ:


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ภายใต้ประทุน ไม่จำเป็นต้องหว่านเมล็ดด้วยตนเองด้วยเห็บนาฬิกา
Mehrdad Afshari

@MehrdadAfshari เป็นอย่างนั้นเสมอไหม?
Chris Marisic

3
แม้ว่านี่คือเมื่อหลายปีก่อนเหตุผลที่ฉันใช้ในการสุ่มใหม่ก็คือฉันได้รับผลลัพธ์ที่แน่นอนเหมือนกันในการทดสอบหน่วยและฉันต้องการความแปรปรวน การใช้ตัวเลขทำให้ฉันแปรปรวน
Chris Marisic

3
บริบทเริ่มต้นคือuncheckedดังนั้นหากคุณไม่ได้เปลี่ยนอย่างชัดเจนดังนั้นuncheckedคำหลัก (ดังที่แสดงในคำตอบนี้และความคิดเห็นของ @ ChrisMarisic ฯลฯ ) ไม่จำเป็นและint myIntValue = (int)myLongValueมีความเท่าเทียมกัน อย่างไรก็ตามโปรดทราบว่าไม่ว่าคุณจะใช้uncheckedคำหลักหรือไม่ก็ตามคุณจะได้รับพฤติกรรมการตัดทอนที่ไม่เกี่ยวกับคณิตศาสตร์ที่อธิบายโดย @TJCrowder ที่ซึ่งสัญญาณสามารถพลิกในบางกรณีที่โอเวอร์โฟลว์ วิธีเดียวที่จะทำให้แน่ใจว่าถูกต้องทางคณิตศาสตร์อย่างแท้จริงคือการใช้checked(...)บริบทซึ่งกรณีเหล่านั้นจะทำให้เกิดข้อยกเว้น
Glenn Slayden

35
Convert.ToInt32(myValue);

แม้ว่าฉันจะไม่รู้ว่ามันจะทำอย่างไรเมื่อมันยิ่งใหญ่กว่า int.MaxValue


42
"แม้ว่าฉันจะไม่รู้ว่ามันจะทำอย่างไรเมื่อมันยิ่งใหญ่กว่า int.MaxValue"มันจะขว้างOverflowExceptionซึ่งเป็นสิ่งที่ OP ต้องการ: 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) ถูกต้องการแปลงเป็นคำตอบที่ดีกว่า ดีกว่าที่จะมีข้อยกเว้นที่แปลกกว่าข้อมูลแปลก ๆ
Richard มิถุนายน

1
@RichardJune อืมมมม? สหกรณ์ที่นี่อย่างชัดเจนกล่าวว่า " ถ้าค่าของยาว> int.MaxValue ผมมีความสุขที่จะให้มันห่อรอบ. " ฉันสามารถดูเถียงคำสั่งของคุณโดยทั่วไป แต่ในกรณีนี้โดยเฉพาะไม่มีConvertไม่ดี
ruffin

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

15

บางครั้งคุณไม่ได้สนใจจริงในมูลค่าที่เกิดขึ้นจริง แต่ในการใช้งานของมันเช่นการตรวจสอบ / แฮชโค้ด ในกรณีนี้วิธีการในGetHashCode()ตัวเป็นตัวเลือกที่ดี:

int checkSumAsInt32 = checkSumAsIn64.GetHashCode();

7
เมื่อไม่นานมานี้นับตั้งแต่ได้รับคำตอบนี้ถึงแม้ว่าฉันต้องการพูดถึงว่าการติดตั้ง hashcode อาจแตกต่างกันระหว่างรุ่น. NET สิ่งนี้อาจไม่ได้เกิดขึ้นจริง แต่ไม่มีการรับประกันว่าค่านี้จะเหมือนกันระหว่างแอพพลิเคชั่น / แอพโดเมนที่ต่างกัน
Caramiriel

1
หากต้องการเพิ่มสิ่งที่ @Caramiriel พูด: หากใช้เป็นแฮชโค้ดชั่วคราวระหว่างช่วงแอปเซสชันปัจจุบันของคุณGetHashCodeจะเป็นตัวเลือกที่เหมาะสม หากคุณอยู่หลังการตรวจสอบอย่างต่อเนื่อง - ค่าที่จะเหมือนกันเมื่อคุณเรียกใช้แอปของคุณในภายหลังไม่ควรใช้GetHashCodeเนื่องจากจะไม่รับประกันว่าจะเป็นอัลกอริทึมเดียวกันตลอดไป
ToolmakerSteve

9

วิธีที่ปลอดภัยและเร็วที่สุดคือการใช้ Bit Masking ก่อนส่ง ...

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

มันสามารถแปลงโดย

วิธีการแปลง. ToInt32

แต่จะโยน OverflowException หากค่านั้นอยู่นอกช่วงของ Int32 Type การทดสอบพื้นฐานจะแสดงให้เราเห็นว่ามันทำงานอย่างไร:

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

บางครั้ง IMHO ดีกว่าที่จะได้รับการยกเว้นมากกว่าค่าที่ไม่ถูกต้องซึ่ง Int32.MaxValue จะเป็น ...
G. Goncharov

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);
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.