ฉันจะแปลงทศนิยมให้เป็น int ใน C # ได้อย่างไร


227

ฉันจะแปลงทศนิยมให้เป็น int ได้อย่างไร


11
มันจะเป็นประโยชน์ที่จะรู้ว่าคุณอยากจะไปรอบ int ที่ใกล้ที่สุดหรือเพียงแค่วางตัวเลขหลังจุดทศนิยม (เช่น: รอบเสมอลง)
ดินาห์

128
ฉันอย่างจริงใจไม่เห็นจุดในการ downvoting คำถามของแท้ ใช่คำตอบสามารถพบได้ใน google แต่มันจะไม่เพียงปรับปรุงคุณภาพของเว็บไซต์ถ้าคนหยุดปิดทุกคำถามที่สอง? ไม่ใช่คำถามนี้เป็นสแปมหรืออะไรและฉันแน่ใจว่ามันจะมีประโยชน์สำหรับผู้มาใหม่จำนวนมากถึง # c # #
jay_t55

คำตอบ:


268

ใช้Convert.ToInt32จากmscorlibใน

decimal value = 3.14m;
int n = Convert.ToInt32(value);

ดูMSDN Decimal.ToInt32นอกจากนี้คุณยังสามารถใช้ อีกครั้งดูMSDN ในที่สุดคุณสามารถทำการส่งโดยตรงเช่นเดียวกับใน

decimal value = 3.14m;
int n = (int) value;

ซึ่งใช้ตัวดำเนินการส่งที่ชัดเจน ดูMSDN


10
ระวัง: การแปลงมีพฤติกรรมที่น่าแปลกใจสำหรับการแปลงบางอย่าง ( nullเทียบ0กับกับ"") ผมอยากแนะนำให้ไม่เคยใช้แปลงถ้าคุณอย่างต้องมีความยืดหยุ่น (เช่นในสถานการณ์พิมพ์แบบไดนามิก)
เอมอน Nerbonne

1
-1 ตั้งแต่นี้จะไม่ทำงานสำหรับค่าเช่น decimal.MaxValue และ decimal.MinValue OverflowExceptionและผลใน ฉันเชื่อว่า @Will จะให้คำตอบที่ดีกว่าที่นี่stackoverflow.com/a/501165/39532
mezoid

8
ระวังเพราะConvert.ToInt32และDecimal.ToInt32ประพฤติแตกต่างกัน จาก MSDN: Decimal.ToInt32- ค่าส่งคืนเป็นส่วนหนึ่งของค่าทศนิยม ตัวเลขที่เป็นเศษจะถูกตัดทอน Convert.ToInt32- ส่งคืนค่าที่ปัดเศษเป็นจำนวนเต็มแบบ 32 บิตที่ใกล้ที่สุด หากค่าอยู่ครึ่งทางระหว่างสองจำนวนเต็มจำนวนคู่จะถูกส่งคืน นั่นคือ 4.5 ถูกแปลงเป็น 4 และ 5.5 ถูกแปลงเป็น 6
vezucci

67

คุณทำไม่ได้

แน่นอนว่าคุณสามารถทำได้อย่างไรก็ตาม int (System.Int32) ไม่ใหญ่พอที่จะเก็บค่าทศนิยมทุกค่าที่เป็นไปได้

นั่นหมายความว่าถ้าคุณใช้ทศนิยมที่มีขนาดใหญ่กว่า int.MaxValue คุณจะล้นและถ้าทศนิยมมีขนาดเล็กกว่า int.MinValue ก็จะไหลล้น

จะเกิดอะไรขึ้นเมื่อคุณอยู่ภายใต้ / ล้น หนึ่งในสองสิ่ง หากบิลด์ของคุณไม่ถูกตรวจสอบ (เช่น CLR ไม่สนใจว่าคุณทำ) แอปพลิเคชันของคุณจะดำเนินการต่อหลังจากค่าเกิน / ต่ำกว่า แต่ค่าใน int จะไม่เป็นอย่างที่คุณคาดไว้ สิ่งนี้สามารถนำไปสู่ข้อบกพร่องเป็นระยะ ๆ และอาจแก้ไขได้ยาก คุณจะสิ้นสุดการสมัครของคุณในสถานะที่ไม่รู้จักซึ่งอาจส่งผลให้แอปพลิเคชันของคุณทำลายข้อมูลสำคัญใด ๆ ที่แอปพลิเคชันทำงาน ไม่ดี.

หากแอสเซมบลีของคุณถูกตรวจสอบ (คุณสมบัติ -> build-> ขั้นสูง -> ตรวจสอบการคำนวณทางคณิตศาสตร์มากเกินไป / อันเดอร์โฟลหรือตัวเลือก / ตรวจสอบคอมไพเลอร์) รหัสของคุณจะโยนข้อยกเว้นเมื่อเกิดภายใต้ / ล้น นี่อาจจะดีกว่าไม่ได้; อย่างไรก็ตามค่าเริ่มต้นสำหรับแอสเซมบลีไม่ได้ตรวจสอบเกิน / underflow

คำถามจริงคือ "คุณพยายามทำอะไร" ไม่มีใครสามารถบอกคุณได้ว่าคุณควรทำอะไรในกรณีนี้นอกเหนือจากที่ชัดเจน: ไม่ต้องทำ

หากคุณไม่สนใจเป็นพิเศษคำตอบที่นี่จะใช้ได้ อย่างไรก็ตามคุณควรสื่อสารความเข้าใจของคุณว่าอาจเกิดโอเวอร์โฟลว์และมันไม่สำคัญโดยการห่อโค้ดคาสต์ของคุณในบล็อกที่ไม่ได้ตรวจสอบ

unchecked
{
  // do your conversions that may underflow/overflow here
}

ด้วยวิธีการที่ผู้คนที่อยู่ข้างหลังคุณเข้าใจว่าคุณไม่สนใจและถ้าในอนาคตมีคนเปลี่ยนงานสร้างของคุณเป็น / ตรวจสอบรหัสของคุณจะไม่ผิดพลาดโดยไม่คาดคิด

หากสิ่งที่คุณต้องการทำคือปล่อยส่วนที่เป็นเศษส่วนของจำนวนออกจากส่วนที่เป็นส่วนประกอบคุณสามารถใช้ Math.Truncate

decimal actual = 10.5M;
decimal expected = 10M;
Assert.AreEqual(expected, Math.Truncate(actual));

3
แม้ว่าฉันสงสัยว่ามันเป็นสิ่งเดียวกันภายใต้ประทุนหากอินพุตเป็นทศนิยม แต่ฉันรู้สึกสบายใจเมื่อใช้ทศนิยมการปัดเศษมากกว่าคณิตศาสตร์การปัดเศษเนื่องจากหลังยังยอมรับคู่เป็นสองเท่าและสามารถเข้าใจได้เพื่อให้สามารถตัดเลขคู่ได้ ที่ไม่ได้เป็นฐาน 10 ซึ่งต่างจากเลขทศนิยมตัดทอนซึ่งเป็นการตัดทอนจำนวนจริง 10 ฐาน
Brian

7
บริบทที่ไม่ได้ตรวจสอบใช้ไม่ได้กับทศนิยม การดำเนินการเกี่ยวกับทศนิยมจะโยน OverflowExceptions ไม่ว่า
เดฟ

46
int i = (int)d;

จะทำให้คุณปัดเศษตัวเลขลง

หากคุณต้องการปัดเศษให้เป็นเลขคู่ที่ใกล้ที่สุด (เช่น> .5 จะปัดเศษขึ้น) คุณสามารถใช้

int i = (int)Math.Round(d, MidpointRounding.ToEven);

โดยทั่วไปคุณสามารถแปลงระหว่างประเภทตัวเลขทั้งหมดใน C # หากไม่มีข้อมูลที่จะหายไประหว่างการส่งนักแสดงคุณสามารถทำได้โดยปริยาย:

int i = 10;
decimal d = i;

แม้ว่าคุณจะสามารถทำได้อย่างชัดเจนหากคุณต้องการ:

int i = 10;
decimal d = (decimal)i;

อย่างไรก็ตามหากคุณกำลังจะสูญเสียข้อมูลผ่านการส่งนักแสดงคุณต้องทำอย่างชัดเจน (เพื่อแสดงให้คุณทราบว่าคุณอาจกำลังสูญเสียข้อมูล):

decimal d = 10.5M;
int i = (int)d;

ที่นี่คุณกำลังสูญเสีย ".5" สิ่งนี้อาจใช้ได้ แต่คุณต้องมีความชัดเจนเกี่ยวกับเรื่องนี้และทำการบล็อกที่ชัดเจนเพื่อแสดงให้คุณรู้ว่าคุณอาจสูญเสียข้อมูล


1
จริง ๆ แล้วคุณต้องการ MidpointRounding.AwayFromZero ถ้าคุณต้องการ> * .5 เสมอไปตามประสบการณ์ของฉันลองใช้โค้ดข้างต้นดูตัวอย่างผลลัพธ์ที่นี่: msdn.microsoft.com/en-us/library/ …
Elijah Lofgren

@ElijahLofgren มันขึ้นอยู่กับว่า: ถ้าคุณกำลังทำสถิติToEvenควรป้องกันการดริฟท์สถิติ หากคุณทำงานกับรายการหรือเงินที่คิดค่าบริการAwayFromZeroดูเหมือนว่าเป็นตัวเลือกที่เหมาะสม
mbx

22
decimal d = 2;
int i = (int) d;

มันน่าจะใช้ได้ดี


ระวังด้วยข้อมูลการแปลงที่ชัดเจนอาจหายไป
Phaedrus

21
เมื่อแปลงจากทศนิยมเป็น int ข้อมูลจะหายไปเกือบตลอดเวลา แต่ฉันเชื่อว่านั่นเป็นประเด็น
ไดน่า


8

System.Decimalใช้IConvertableอินเตอร์เฟสซึ่งมีToInt32()สมาชิก

การโทรSystem.Decimal.ToInt32()หาคุณหรือไม่


2
จากเอกสารประกอบ : "API นี้รองรับโครงสร้างพื้นฐาน. NET Framework และไม่ได้มีวัตถุประสงค์เพื่อใช้โดยตรงจากรหัสของคุณ" ทำไมไม่ใช้ Convert.ToInt32
H.Wolper

7

เคล็ดลับที่เป็นระเบียบสำหรับการปัดเศษอย่างรวดเร็วคือการเพิ่ม 0.5 ก่อนที่คุณจะแปลงทศนิยมเป็น int

decimal d = 10.1m;
d += .5m;
int i = (int)d;

ยังคงออกจากi=10แต่

decimal d = 10.5m;
d += .5m;
int i = (int)d;

i=11จะปัดเศษขึ้นเพื่อให้


5
ทำไมต้องทำเช่นนี้เมื่อมี Math.Floor และ Math.Ceiling?
Badaro

ในเวลานั้นฉันค่อนข้างใหม่กับ C # และด้วยเหตุผลบางอย่างที่ฉันไม่ได้ตระหนักถึงฟังก์ชั่นเหล่านี้อยู่ มันเป็นเคล็ดลับที่ฉันเรียนรู้จาก C / C ++ ซึ่งมันมีประโยชน์มากกว่าอย่างเห็นได้ชัด
DeadlyBrad42

1
เกิดอะไรขึ้นถ้าค่าทศนิยมเป็น -9.3?
supercat

6

ฉันชอบใช้Math.Round , Math.Floor , Math.CeilingหรือMath.Truncateเพื่อกำหนดโหมดการปัดเศษอย่างเหมาะสมตามความเหมาะสม

โปรดทราบว่าพวกเขาทั้งหมดกลับทศนิยมเช่นกัน - เนื่องจากทศนิยมมีช่วงที่มีค่ามากกว่า Int32 ดังนั้นคุณจะยังคงต้องส่ง (และตรวจสอบล้น / อันเดอร์โฟล์)

 checked {
   int i = (int)Math.Floor(d);
 }


6

การปัดเศษทศนิยมเป็นจำนวนเต็มที่ใกล้ที่สุด

decimal a ;
int b = (int)(a + 0.5m);

เมื่อa = 49.9แล้วb = 50

เมื่อa = 49.5แล้วb = 50

เมื่อa = 49.4แล้วb = 49ฯลฯ


0

ฉันพบว่าตัวดำเนินการแคสต์ไม่ทำงานหากคุณมีทศนิยมแบบกล่อง (เช่นค่าทศนิยมภายในประเภทวัตถุ) Convert.ToInt32 (ทศนิยมเป็นวัตถุ) ทำงานได้ดีในกรณีนี้

สถานการณ์นี้เกิดขึ้นเมื่อดึงค่า IDENTITY / AUTONUMBER จากฐานข้อมูล:

SqlCommand foo = new SqlCommand("INSERT INTO...; SELECT SCOPE_IDENTITY()", conn);
int ID = Convert.ToInt32(foo.ExecuteScalar());  // works
int ID = (int)foo.ExecuteScalar();              // throws InvalidCastException

ดูที่4.3.2 การแปลง Unboxing


2
เพิ่มมากขึ้นสำหรับการอ้างอิง: นั่นเป็นเพราะคุณสามารถ unbox ไปเป็นประเภทเดิมเท่านั้น ที่นี่SELECT SCOPE_IDENTITY()ส่งกลับnumeric(38, 0)ซึ่งแปลdecimalโดย. NET foo.ExecuteScalar()ส่งกลับdecimalชนิดบรรจุกล่องเป็นที่ไม่สามารถออกเสียงโดยตรงกับobject หรือจะทำงาน int(int)(decimal)foo.ExecuteScalar()Convert.ToInt32(foo.ExecuteScalar())
rageit

0

ดูเหมือนว่าไม่มีคำตอบที่จะจัดการกับ OverflowException / UnderflowException ที่มาจากการพยายามแปลงทศนิยมที่อยู่นอกช่วงของ int

int intValue = (int)Math.Max(int.MinValue, Math.Min(int.MaxValue, decimalValue));

วิธีนี้จะคืนค่า int สูงสุดหรือต่ำสุดที่เป็นไปได้ถ้าค่าทศนิยมอยู่นอกช่วง int คุณอาจต้องการเพิ่มการปัดเศษด้วย Math.Round, Math.Ceiling หรือ Math.Floor เมื่อค่านั้นอยู่ในช่วง int

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