วิธีที่ดีที่สุดในการรับส่วนจำนวนเต็มของจำนวนทศนิยม


91

วิธีใดเป็นวิธีที่ดีที่สุดในการคืนค่าส่วนจำนวนเต็มของทศนิยม (ใน c #) (ต้องใช้กับตัวเลขที่มีขนาดใหญ่มากซึ่งอาจไม่พอดีกับ int)

GetIntPart(343564564.4342) >> 343564564
GetIntPart(-323489.32) >> -323489
GetIntPart(324) >> 324

จุดประสงค์ของสิ่งนี้คือ: ฉันกำลังแทรกลงในฟิลด์ทศนิยม (30,4) ในฐานข้อมูลและต้องการให้แน่ใจว่าฉันไม่ได้พยายามแทรกตัวเลขที่ยาวเกินไปสำหรับฟิลด์ การกำหนดความยาวของส่วนจำนวนเต็มของทศนิยมเป็นส่วนหนึ่งของการดำเนินการนี้


คุณไม่สามารถรับส่วน int; คุณจะได้รับส่วนจำนวนเต็มและทิ้งส่วนที่เป็นเศษส่วน ส่วนจำนวนเต็มของทศนิยมสามารถล้น int ได้อย่างง่ายดายและโยนหรือล้อมรอบฆ่ารหัสของคุณอย่างเงียบ ๆ

1
นั่นคือเหตุผลที่คำถามนี้ไม่ง่ายอย่างที่คิด ฉันต้องการสิ่งนี้เพื่อทำงานกับตัวเลขขนาดใหญ่อย่างน่าเชื่อถือเช่นเดียวกับตัวเลขขนาดเล็ก อย่างไรก็ตาม "จำนวนเต็ม" มีความถูกต้องมากกว่า "int" - ฉันจะเขียนซ้ำด้านบน
Yaakov Ellis

คำตอบ:


215

อย่างไรก็ตามพวก (int) ทศนิยม MaxValue จะล้น คุณไม่สามารถรับส่วน "int" ของทศนิยมได้เนื่องจากทศนิยมมีขนาดใหญ่เกินไปที่จะใส่ลงในช่อง int เพิ่งตรวจสอบ ... มันใหญ่เกินไปสำหรับระยะยาว (Int64)

หากคุณต้องการให้บิตของค่าทศนิยมอยู่ทางซ้ายของจุดคุณต้องทำสิ่งนี้:

Math.Truncate(number)

และคืนค่าเป็น ... DECIMAL หรือ DOUBLE

แก้ไข: Truncate เป็นฟังก์ชันที่ถูกต้องแน่นอน!


ดังนั้นผลลัพธ์จึงเป็นทศนิยมหรือสองเท่าที่จะไม่มีอะไรเลยหลังจากจุด แต่ไม่มีอ็อบเจ็กต์ในตัวเพื่อเก็บผลลัพธ์เป็น "int" (ไม่มีตำแหน่งทศนิยม) ซึ่งดูเหมือนจะง่อยไปหน่อย?
สุ่ม

@CodeBlend: ไม่มีการเรียกร้องให้ออกแบบกรอบงานเกี่ยวกับความปรารถนาที่จะสูญเสียความแม่นยำมากนัก

@CodeBlend: คุณจะยังคงสูญเสียความแม่นยำเพราะคุณกำลังตัดค่าทศนิยมของตัวเลข ไม่แน่ใจว่าคุณกำลังทำอะไรอยู่

ไม่แน่ใจว่าจะได้ผลหรือไม่ เพราะ Math.Truncate (-5.99999999999999999) คืนค่า -6.0 ให้ผม ... !!
Bharat Mori

@Bharat Mori: ดูเหมือนว่า -5.99999999999999999 จะถูกปัดเศษเป็น -6.0 ก่อนที่จะตัดทอน ลองใช้คำต่อท้าย "m" ก็ใช้ได้ Math.Truncate (-5.99999999999999999m) ให้ -5
Henry


4

ขึ้นอยู่กับสิ่งที่คุณกำลังทำ

ตัวอย่างเช่น:

//bankers' rounding - midpoint goes to nearest even
GetIntPart(2.5) >> 2
GetIntPart(5.5) >> 6
GetIntPart(-6.5) >> -6

หรือ

//arithmetic rounding - midpoint goes away from zero
GetIntPart(2.5) >> 3
GetIntPart(5.5) >> 6
GetIntPart(-6.5) >> -7

เริ่มต้นอยู่เสมอในอดีตซึ่งสามารถจะแปลกใจ แต่จะทำให้ความรู้สึกที่ดีมาก

นักแสดงที่ชัดเจนของคุณจะทำ:

int intPart = (int)343564564.5
// intPart will be 343564564

int intPart = (int)343564565.5
// intPart will be 343564566

จากวิธีที่คุณตั้งคำถามดูเหมือนว่านี่ไม่ใช่สิ่งที่คุณต้องการ - คุณต้องการปูพื้นทุกครั้ง

ฉันจะทำ:

Math.Floor(Math.Abs(number));

ตรวจสอบขนาดของคุณด้วยdecimal- อาจมีขนาดค่อนข้างใหญ่ดังนั้นคุณอาจต้องใช้ไฟล์long.


(ยาว) ทศนิยม MaxValue ล้น

จุดยุติธรรม - ฉันเดาว่านั่นคือสาเหตุที่ Math.Truncate (decimal) ส่งคืนทศนิยม
Keith

ใน C # การแคสต์เป็น int จะไม่ปัดเศษดังนั้น (int) 0.6f จะเป็น 0 และ (int) 343564565.5 จะสิ้นสุดใน 5 ไม่ใช่ 6 ลองที่นี่: repl.it/repls/LuxuriousCheerfulDistributeddatabase
sschmidTU

0

คุณเพียงแค่ต้องแคสต์ดังต่อไปนี้:

int intPart = (int)343564564.4342

หากคุณยังต้องการใช้เป็นทศนิยมในการคำนวณในภายหลังดังนั้น Math.Truncate (หรืออาจเป็น Math.Floor หากคุณต้องการให้มีพฤติกรรมบางอย่างสำหรับตัวเลขเชิงลบ) คือฟังก์ชันที่คุณต้องการ


5
นี่คือผิดผิดผิด หากผลลัพธ์มากกว่าที่ Int32 สามารถเก็บไว้ได้มันจะทำให้เกิดข้อยกเว้นหรือ (แย่ยิ่งกว่านั้น !!!) ล้นออกมาอย่างเงียบ ๆ และห่อกลับรอบทำให้คุณได้ผลลัพธ์ที่ไม่ถูกต้องโดยที่คุณไม่รู้ด้วยซ้ำ

2
ไม่มีก็ไม่ผิด หลายค่าใช้ไม่ได้กับทศนิยม / ทศนิยมที่มีขนาดใหญ่มาก แต่เหมาะอย่างยิ่งสำหรับสถานการณ์ส่วนใหญ่ ตัวเลขมักถูก จำกัด ให้ต่ำพอในการเขียนโค้ดดังนั้นจึงไม่จำเป็นต้องมีปัญหา นอกจากนี้ฉันยังให้โซลูชัน Math.Truncate ที่ใช้ได้กับทุกค่า
Noldorin

2
ฉันเห็นว่าทำไมคุณถึงโกรธฉัน ความจริงก็คือคำตอบของคุณผิด คุณกำลังบอกให้เขามีโอกาสที่จะไม่ทำลายเพราะเดี๋ยวก่อนตัวเลขจำนวนมากมีน้อย มันเป็นความเสี่ยงที่โง่เขลาที่จะรับ คุณควรแก้ไขคำตอบของคุณและลบทุกอย่างยกเว้น Math.Truncate เป็นส่วนที่ถูกต้องเท่านั้น

1
คุณรู้ว่าพวกเขาพูดอะไรเกี่ยวกับ ASSUME นอกจากนี้สมมติฐานของคุณยังแย่มาก อักเสบหรือเปล่า ฉันเดาว่าคุณคงพูดแบบนั้น คุณยังสามารถพูดได้ว่าการบอกให้ใครบางคนทำสิ่งที่โง่เขลาซึ่งจะทำให้พวกเขามีปัญหาบนท้องถนนก็เป็นเรื่องที่น่าปวดหัวได้เช่นกันหากไม่ทำผิดจรรยาบรรณ

1
แน่นอนว่าจะผิดถ้าฉันตั้งใจจะให้คำตอบที่ทำให้เข้าใจผิด เหมือนเดิมฉันแค่พยายามช่วย หากฉันมีความผิดที่เข้าใจผิดเล็กน้อยหรือไม่เข้าใจคำถามอย่างเต็มที่นั่นก็ยุติธรรมเพียงพอแล้ว - ไม่ใช่อาชญากรรม แล้วทำไมเราถึงเถียงกันตอนนี้? เราทุกคนยอมรับว่า Truncate เป็นคำตอบที่ถูกต้อง
Noldorin

0

วิธีที่ง่ายมากในการแยกมูลค่าและค่าเศษส่วน

double  d = 3.5;
int i = (int)d;
string s = d.ToString();
s = s.Replace(i + ".", "");

s คือส่วนเศษส่วน = 5 และ
i คือค่าเป็นจำนวนเต็ม = 3


1
ดูคำตอบด้านบนด้านบน วิธีนี้ใช้ไม่ได้เพราะ(int)Decimal.MaxValueจะล้น
Yaakov Ellis

0

ฉันหวังว่าจะช่วยคุณ

/// <summary>
/// Get the integer part of any decimal number passed trough a string 
/// </summary>
/// <param name="decimalNumber">String passed</param>
/// <returns>teh integer part , 0 in case of error</returns>
private int GetIntPart(String decimalNumber)
{
    if(!Decimal.TryParse(decimalNumber, NumberStyles.Any , new CultureInfo("en-US"), out decimal dn))
    {
        MessageBox.Show("String " + decimalNumber + " is not in corret format", "GetIntPart", MessageBoxButtons.OK, MessageBoxIcon.Error);
        return default(int);
    } 

    return Convert.ToInt32(Decimal.Truncate(dn));
}

-2
   Public Function getWholeNumber(number As Decimal) As Integer
    Dim round = Math.Round(number, 0)
    If round > number Then
        Return round - 1
    Else
        Return round
    End If
End Function

1
คำตอบที่ได้รับการยอมรับโพสต์เมื่อกว่าแปดปีที่แล้วอธิบายว่าทำไมคำตอบนี้จึงไม่ถูกต้อง ช่วงของอยู่ไกลเกินกว่าที่decimal intนอกจากนี้นี่ไม่ใช่คำถาม VB
Joe Farrell

@JoeFarrell - ถ้าคุณรู้สึกว่าคำตอบไม่ถูกต้องคุณสามารถพิจารณาลงคะแนนได้นอกเหนือจากการแสดงความคิดเห็นต่อเอฟเฟกต์ อย่างไรก็ตามอย่าตั้งค่าสถานะ (ไม่ใช่ว่าฉันบอกว่าคุณมี) เป็นความพยายามที่จะตอบคำถาม มันอาจจะเป็นภาษาที่ไม่ถูกต้องมันอาจจะผิดแม้ใน VB แต่มันเป็นความพยายาม ดูตัวอย่างเช่น " เมื่อคำตอบตอบคำถามผิดคำตอบนั้นไม่ใช่คำตอบหรือไม่ "
Wai Ha Lee
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.