ประเภทข้อมูลที่ดีที่สุดที่จะใช้สำหรับเงินใน C # คืออะไร?


426

ประเภทข้อมูลที่ดีที่สุดที่จะใช้สำหรับเงินใน C # คืออะไร?


4
คุณอาจพบคำตอบจากโพสต์นี้เป็นประโยชน์
ntombela

นี่คือการแมปสำหรับประเภทข้อมูลทั้งหมด: docs.microsoft.com/en-us/dotnet/framework/data/adonet/ ......
JohnLBevan

นอกจากนี้หากใช้คำอธิบายประกอบข้อมูลให้รวมusing System.ComponentModel.DataAnnotations;... [DataType(DataType.Currency)] msdn.microsoft.com/en-us/library/
JohnLBevan

คำตอบ:


422

ตามที่อธิบายไว้ในทศนิยมเป็น:

คำสำคัญทศนิยมระบุชนิดข้อมูล 128 บิต เมื่อเปรียบเทียบกับทศนิยมชนิดทศนิยมจะมีความแม่นยำมากกว่าและมีขนาดเล็กกว่าซึ่งเหมาะสำหรับการ คำนวณทางการเงินและการเงิน

คุณสามารถใช้ทศนิยมดังนี้

decimal myMoney = 300.5m;

41
คุณควรอธิบายสิ่งที่เกี่ยวกับลิงค์นั้นสำคัญ คำตอบควรจะดีพอสำหรับตัวมันเองพร้อมลิงค์สำหรับอ้างอิงหรือรายละเอียดเพิ่มเติม ดูstackoverflow.com/help/how-to-answer
TheRubberDuck

2
ดังนั้นคำตอบที่มีความยาวต่ำสุดอาจเป็นอักขระน้อยกว่าความคิดเห็นที่มีความยาวต่ำ - น่าสนใจ! ไม่ใช่ว่าฉันมีปัญหากับคำตอบสั้น / กระชับโดยเฉพาะอย่างยิ่งเมื่อมันยัง "ลึก" ในการที่จะเชื่อมโยงไปยังการอภิปรายต่อไป
B. Clay Shannon

3
คำตอบที่น่าอัศจรรย์และฉันไม่รู้สึกว่ามันต้องการคำอธิบายเพิ่มเติมเพราะมันตอบคำถามได้อย่างสมบูรณ์ ลิงก์ไปยังเอกสาร MSDN เป็นโบนัสเท่าที่ฉันกังวล ไชโย!
trnelson

@Leee Treveil เงินเป็นอย่างไร (9.0098) หมายถึง 4 ตัวละครหลังพอยต์
SAR

114

System.Decimal

ประเภทค่าทศนิยมแสดงถึงตัวเลขทศนิยมตั้งแต่บวก 79,228,162,514,264,337,593,43,950,335 ถึงลบ 79,228,162,514,264,337,593,335,335,335 ประเภทค่าทศนิยมเหมาะสำหรับการคำนวณทางการเงินที่ต้องการตัวเลขจำนวนหนึ่งและตัวเลขเศษส่วนจำนวนมากและไม่มีข้อผิดพลาดในการปัดเศษ ประเภททศนิยมไม่กำจัดความจำเป็นในการปัดเศษ ค่อนข้างจะช่วยลดข้อผิดพลาดเนื่องจากการปัดเศษ

ฉันต้องการจะชี้ไปที่คำตอบที่ยอดเยี่ยมนี้โดย zneak ว่าทำไมไม่ควรใช้ double


68

ใช้รูปแบบเงินจากรูปแบบของสถาปัตยกรรม Enterprise Application ; ระบุจำนวนเป็นทศนิยมและสกุลเงินเป็น enum


2
จริง ๆ แล้วฉันจะแนะนำสิ่งนี้ แต่ฉันทำให้สกุลเงินเป็นคลาสเพื่อให้ฉันสามารถกำหนดอัตราแลกเปลี่ยน (ในความสัมพันธ์กับ "สกุลเงินพื้นฐาน" ซึ่งมักจะเป็นสกุลเงินดอลลาร์สหรัฐ
Thomas Owens

5
สำหรับผู้เยี่ยมชมในอนาคตของหัวข้อนี้ (เช่นฉัน) ตอนนี้มีสิ่งนี้: nuget.org/packages/Moneyและมันจะสั่นสะเทือน !
Korijn

สงสัยว่าประเภทดังกล่าวควรเป็น struct หรือคลาส ทศนิยม + an (int) enum ทำให้มีขนาด 20 ไบต์ เงินของฉันยังคงมีโครงสร้าง
nawfal

นั่นMoneynuget มีการเชื่อมโยง GitHub ตายสำหรับเว็บไซต์ของโครงการดังนั้น ... ไม่มีเอกสาร?
George Mauer

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

25

ทศนิยม. หากคุณเลือกสองครั้งคุณจะปล่อยให้ตัวเองเปิดข้อผิดพลาดในการปัดเศษ


8
@Jess doubleสามารถแนะนำข้อผิดพลาดในการปัดเศษได้เนื่องจากจุดลอยตัวไม่สามารถแสดงตัวเลขทั้งหมดได้อย่างแน่นอน (เช่น 0.01 ไม่มีการแทนค่าแน่นอนในจุดลอยตัว) Decimalบนมืออื่น ๆ ที่ไม่แสดงตัวเลขว่า (การแลกเปลี่ยนDecimalมีช่วงที่เล็กกว่าจุดลอยตัว) จุดลอยตัวสามารถทำให้คุณเกิดข้อผิดพลาดในการปัดเศษ * โดยไม่ตั้งใจ * (เช่น0.01+0.01 != 0.02) Decimalสามารถให้ปัดเศษข้อผิดพลาด แต่เฉพาะเมื่อคุณถามมัน (เช่นMath.Round(0.01+0.02)ผลตอบแทนเป็นศูนย์)
เอียนบอยด์

2
@IanBoyd: ค่า "$ 1.57" สามารถแสดงได้อย่างแม่นยำ (สองครั้ง) 157 หากมีใครใช้doubleและใช้การปรับขนาดและการปัดเศษเฉพาะโดเมนอย่างรอบคอบเมื่อเหมาะสมจะสามารถแม่นยำได้อย่างสมบูรณ์แบบ หากมีใครเลอะเทอะในการปัดเศษdecimalอาจให้ผลลัพธ์ที่ไม่ถูกต้องทางความหมาย (เช่นถ้ามีการรวมค่าหลายค่าเข้าด้วยกันซึ่งควรจะถูกปัดเศษเป็นเพนนีที่ใกล้เคียงที่สุด สิ่งเดียวที่ดีเกี่ยวกับการdecimalปรับขนาดนั้นก็คือการติดตั้งในตัว
supercat

1
@supercat เกี่ยวกับความคิดเห็นนี้ "ถ้ามีการรวมค่าหลายค่าเข้าด้วยกันซึ่งควรจะถูกปัดเศษเป็นเงินที่ใกล้ที่สุด เป็นข้อผิดพลาดของผู้ใช้และไม่เกี่ยวข้องกับทศนิยม IMHO ฉันได้รับจุด แต่ฉันรู้สึกว่ามันถูกวางผิดส่วนใหญ่เพราะ IanBoyd ไม่ได้ระบุว่า ... หากคุณขอมัน
เลื่อย


13

เห็นด้วยกับรูปแบบเงิน: การจัดการสกุลเงินนั้นยุ่งยากเกินไปเมื่อคุณใช้ทศนิยม

หากคุณสร้างคลาสสกุลเงินคุณสามารถใส่ตรรกะทั้งหมดที่เกี่ยวข้องกับเงินในนั้นรวมถึงวิธี ToString () - ที่ถูกต้องการควบคุมค่าการแยกวิเคราะห์และการควบคุมแผนกที่ดียิ่งขึ้น

นอกจากนี้ในระดับสกุลเงินไม่มีโอกาสที่จะผสมเงินกับข้อมูลอื่นโดยไม่ได้ตั้งใจ


10

ตัวเลือกอื่น (โดยเฉพาะถ้าคุณกลิ้งชั้นของคุณเอง) คือการใช้ int หรือ int64 และกำหนดตัวเลขสี่หลักที่ต่ำกว่า (หรืออาจเป็น 2) เป็น "ด้านขวาของจุดทศนิยม" ดังนั้น "ที่ขอบ" คุณจะต้องมี "* 10000" ระหว่างทางและบางส่วน "/ 10000" ใกล้ทางออก นี่คือกลไกการจัดเก็บที่ใช้โดย SQL Server ของ Microsoft ดูhttp://msdn.microsoft.com/en-au/library/ms179882.aspx

ความสำคัญของสิ่งนี้คือการสรุปทั้งหมดของคุณสามารถทำได้โดยใช้เลขคณิตจำนวนเต็ม (เร็ว)


7

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

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

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

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

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

และมันก็ไม่ใช่เรื่องยากที่จะใช้อย่างอื่นนอกจากทศนิยม Google "ประเภทเงินนักเก็ต" และคุณจะเห็นว่านักพัฒนาจำนวนมากได้สร้าง abstractions (รวมถึงฉันด้วย) มันเป็นเรื่องง่าย มันเป็นเรื่องง่ายเหมือนการใช้แทนการจัดเก็บในวันที่DateTimestring


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