ร่ายตัวแปรสองเท่าเป็นทศนิยม


96

วิธีการหนึ่งโยนdoubleไปdecimalซึ่งจะใช้เมื่อทำพัฒนาสกุลเงิน ไม่Mไปไหน?

decimal dtot = (decimal)(doubleTotal);

คำตอบ:


85

คุณใช้Mสำหรับลิเทอรัลตัวเลขเท่านั้นเมื่อคุณแคสต์มันเป็นเพียง:

decimal dtot = (decimal)doubleTotal;

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


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

4
@Cortana: ความแม่นยำของทศนิยมสูงกว่า แต่ช่วงจะเล็กกว่า ค่าสองค่าอาจอยู่นอกช่วงสำหรับทศนิยม ดู: stackoverflow.com/questions/7817866/…
Guffa

41

คุณสามารถเพิ่มทวีคูณเป็นทศนิยมเช่นนี้โดยไม่จำเป็นต้องมีMคำต่อท้ายตามตัวอักษร:

double dbl = 1.2345D;
decimal dec = (decimal) dbl;

คุณควรใช้Mเมื่อประกาศค่าทศนิยมตามตัวอักษรใหม่:

decimal dec = 123.45M;

(หากไม่มีM123.45 จะถือว่าเป็นสองเท่าและจะไม่รวบรวม)


28

ใช้คลาสการแปลงเริ่มต้น: Convert.ToDecimal(Double)


1
ไม่ใช่เพราะมันจะโยน OverflowException double vol_y = (double) Decimal.MaxValue + 10E + 28D; Console.WriteLine ("Convert ToDecimal (vol_y) =" + Convert ToDecimal (vol_y));
ToXinE

2
@ToXinE IMHO ในกรณีส่วนใหญ่ OverflowException ดีกว่าการสร้างข้อมูลที่ไม่ถูกต้องอย่างเงียบ ๆ
นี่ตัวเอง

16
Convert.ToDecimal(the double you are trying to convert);

2
ฉันได้เรียนรู้ว่าคลาส Convert นั้นยืดหยุ่นและปลอดภัยกว่าการแคสต์ใน C # มาก
ทอม

3
"ปลอดภัย"? เช่นเดียวกับเมื่อมันไม่สามารถส่งได้มันจะส่งข้อยกเว้นในเวลาทำงานแทนที่จะเป็นข้อผิดพลาดของคอมไพเลอร์? ฉันถูกกัดหลายครั้งจนหลีกเลี่ยงการแปลง ...
Peter Ritchie

8
เธรด @PeterRitchie ค่อนข้างเก่า แต่ควรกล่าวว่า: การเรียกใช้วิธีการแปลงโดยตรงจะเป็นวิธีที่เหมาะสมกว่า บางทีฉันอาจจะเป็นแค่คนที่คลั่งไคล้ในการปรับให้เหมาะสม แต่มีคำแนะนำน้อยกว่าในการแก้ไขคือโบนัส (เนื่องจากการใช้ไวยากรณ์การแคสต์ที่ชัดเจน (ประเภท) เป็นเพียงตัวดำเนินการที่เกินพิกัดที่เรียกว่า Convert)
Mike Johnson

2
@PeterRitchie: จากมุมมองของการออกแบบภาษามันจะเป็นการดีกว่าที่จะกำหนดให้โปรแกรมเมอร์ใช้วิธีการแปลงหนึ่งในสองวิธีแทนที่จะอนุญาตให้ใช้ตัวพิมพ์จากdoubleถึงdecimalเป็นเนื่องจากdoubleค่าเช่น (1000000.0 / 3.0) ในบางกรณี ต้องการคลิปความแม่นยำ "ส่วนเกิน" ที่ให้ผล 333333.333333333D แต่ในกรณีอื่น ๆ เราต้องการเก็บรักษาไว้โดยให้ผล 333333.333333333313931D แทนที่จะพูดว่า "แปลงเป็นทศนิยม" โค้ดควรระบุว่าควรดำเนินการแปลงอย่างไร
supercat

2
@supercat ซึ่งดูเหมือนจะไม่เกี่ยวข้องกับความคิดเห็นแรกของฉันจริงๆเพราะการใช้Convert.ToDecimal(double)นั้นเหมือนกับ(decimal)doubleTotalยกเว้นถ้าdoubleTotalเปลี่ยนเป็นประเภทอื่นคุณอาจหลีกเลี่ยงข้อผิดพลาดเวลาคอมไพล์และแนะนำข้อผิดพลาดรันไทม์ที่หายากกว่าเนื่องจากToDecimal ที่แตกต่างกันการแทนที่อาจถูกเรียก ผู้ดำเนินรายการมีความชัดเจนกว่ามาก ...
Peter Ritchie

1

นี่เป็นคำถามเก่าและฉันได้ใช้คำตอบบางส่วนที่แสดงไว้ที่นี่ อย่างไรก็ตามในสถานการณ์โดยเฉพาะอย่างยิ่งของฉันมันเป็นไปได้ว่าdoubleค่าที่ผมอยากจะแปลงไปก็มักจะมีขนาดใหญ่กว่าdecimal decimal.MaxValueดังนั้นแทนที่จะจัดการข้อยกเว้นฉันเขียนวิธีการขยายนี้:

    public static decimal ToDecimal(this double @double) => 
        @double > (double) decimal.MaxValue ? decimal.MaxValue : (decimal) @double;

วิธีการข้างต้นใช้งานได้หากคุณไม่ต้องการกังวลกับการจัดการข้อยกเว้นล้นและหากสิ่งนั้นเกิดขึ้นคุณต้องการเพียงแค่รักษาค่าสูงสุดที่เป็นไปได้ (กรณีของฉัน) แต่ฉันทราบว่าสำหรับสถานการณ์อื่น ๆ อีกมากมายสิ่งนี้จะไม่ใช่พฤติกรรมที่คาดไว้ และอาจจำเป็นต้องมีการจัดการข้อยกเว้น


1
สิ่งนี้จะล้มเหลวในกรณีต่อไปนี้ double _double = (double) decimal.MaxValue; ฉันขอแนะนำให้ใช้> = ในการเปรียบเทียบทศนิยมสาธารณะแบบคงที่ ToDecimal (คู่นี้ _double) => _double> = (double) decimal.MaxValue? decimal.MaxValue: (ทศนิยม) _double;
Martin Eyles
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.