Loại dữ liệu tốt nhất để sử dụng tiền trong C # là gì?


426

Loại dữ liệu tốt nhất để sử dụng tiền trong C # là gì?


4
Bạn có thể tìm thấy câu trả lời từ bài viết này hữu ích.
ntombela

Đây là một ánh xạ cho tất cả các loại dữ liệu: docs.microsoft.com/en-us/dotnet/framework/data/adonet/ mẹo
JohnLBevan

Ngoài ra, nếu sử dụng chú thích dữ liệu, hãy bao gồm using System.ComponentModel.DataAnnotations;... [DataType(DataType.Currency)] msdn.microsoft.com/en-us/l
Library / 14

Câu trả lời:


421

Như được mô tả ở dạng thập phân là:

Từ khóa thập phân chỉ ra loại dữ liệu 128 bit. So với các loại dấu phẩy động, loại thập phân có độ chính xác cao hơn và phạm vi nhỏ hơn, điều này phù hợp với các tính toán tài chính và tiền tệ .

Bạn có thể sử dụng số thập phân như sau:

decimal myMoney = 300.5m;

41
Bạn nên giải thích những gì về liên kết đó là quan trọng. Một câu trả lời phải đủ tốt, với một liên kết là tài liệu tham khảo hoặc chi tiết bổ sung. Xem stackoverflow.com/help/how-to-answer
TheRubberDuck

2
Vì vậy, câu trả lời có độ dài tối thiểu có thể ít ký tự hơn bình luận có độ dài tối thiểu - thật thú vị! Không phải là tôi có vấn đề với câu trả lời ngắn gọn / súc tích, đặc biệt là khi nó cũng "sâu sắc" ở chỗ nó liên kết để thảo luận thêm.
B. Clay Shannon

3
Câu trả lời tuyệt vời, và tôi không cảm thấy cần giải thích thêm vì nó hoàn toàn trả lời câu hỏi. Liên kết đến tài liệu MSDN là một phần thưởng theo như tôi quan tâm. Bravo!
trnelson

@Leee Treveil, số tiền này như thế nào (9.0098) có nghĩa là 4 ký tự sau Điểm
SAR

114

Hệ thống tối ưu

Loại giá trị thập phân biểu thị các số thập phân từ dương 79,228,162,514,264,337,593,543,950,335 đến âm 79,228,162,514,264,337,593,543,950,335. Loại giá trị thập phân phù hợp cho các tính toán tài chính yêu cầu số lượng lớn các chữ số phân số và tích phân đáng kể và không có sai số làm tròn. Loại thập phân không loại bỏ sự cần thiết phải làm tròn. Thay vào đó, nó giảm thiểu các lỗi do làm tròn.

Tôi muốn chỉ ra câu trả lời tuyệt vời này của zneak về lý do tại sao không nên sử dụng gấp đôi.


68

Sử dụng mẫu Tiền từ Mô hình Kiến trúc Ứng dụng Doanh nghiệp ; chỉ định số tiền dưới dạng thập phân và tiền tệ dưới dạng enum.


2
Tôi thực sự sẽ đề xuất điều này, nhưng tôi biến Tiền tệ thành một lớp để tôi có thể xác định tỷ giá hối đoái (liên quan đến "tiền tệ cơ bản", thường là đô la Mỹ [mà tôi đặt là có tỷ giá hối đoái 1,00]).
Thomas Owens

5
Đối với những khách truy cập tương lai của chủ đề này (như tôi), giờ đã có cái này: nuget.org/packages/Money và nó đá!
Korijn

Tự hỏi nếu một loại như vậy nên là một cấu trúc hoặc lớp. Số thập phân + an (int) làm cho nó 20 byte. Tiền của tôi vẫn còn trên struct.
nawfal

Cái Moneynuget đó có một liên kết github đã chết cho trang web của dự án nên ... không có tài liệu?
George Mauer

Vấn đề với điều này là nếu bạn đang tạo ra triển khai của riêng mình, bạn phải tìm ra cách thực sự duy trì nó. Và ORM (EF) phổ biến nhất hoàn toàn không hỗ trợ cho các loại dữ liệu tùy chỉnh. Do đó ai đó đang yêu cầu để có được thực sự sâu trong cỏ dại để làm những gì nên được một điều khá đơn giản.
George Mauer

25

Số thập phân. Nếu bạn chọn gấp đôi, bạn sẽ để mình bị lỗi làm tròn


8
@Jess doublecó thể đưa ra các lỗi làm tròn bởi vì dấu phẩy động không thể biểu diễn chính xác tất cả các số (ví dụ: 0,01 không có biểu diễn chính xác trong dấu phẩy động). DecimalMặt khác, không đại diện cho số chính xác . (Sự cân bằng Decimalcó phạm vi nhỏ hơn điểm nổi) Điểm nổi có thể gây ra lỗi * làm tròn * vô ý (ví dụ 0.01+0.01 != 0.02). Decimalcó thể cung cấp cho bạn các lỗi làm tròn, nhưng chỉ khi bạn yêu cầu (ví dụ Math.Round(0.01+0.02)trả về 0)
Ian Boyd

2
@IanBoyd: Giá trị "$ 1,57" có thể được biểu diễn chính xác (gấp đôi) 157. Nếu một người sử dụng doublevà áp dụng cẩn thận tỷ lệ và làm tròn theo miền cụ thể khi thích hợp, nó có thể hoàn toàn chính xác. Nếu một người cẩu thả trong làm tròn số của một người, decimalcó thể mang lại kết quả không chính xác về mặt ngữ nghĩa (ví dụ: nếu người ta cộng nhiều giá trị được cho là làm tròn đến đồng xu gần nhất, nhưng thực tế không phải xung quanh chúng trước). Điều tốt duy nhất decimallà quy mô được tích hợp sẵn.
supercat

1
@supercat, liên quan đến nhận xét này "nếu người ta cộng nhiều giá trị được cho là làm tròn đến đồng xu gần nhất, nhưng thực tế không phải xung quanh chúng trước", tôi không thấy cách thả nổi sẽ giải quyết điều này. Đó là lỗi người dùng và không liên quan gì đến số thập phân IMHO. Tôi nhận được điểm nhưng tôi cảm thấy nó đã bị đặt sai chỗ, chủ yếu là vì IanBoyd đã xác định rằng ... nếu bạn yêu cầu.
cưa


13

Đồng ý với mẫu Tiền: Xử lý tiền tệ quá cồng kềnh khi bạn sử dụng số thập phân.

Nếu bạn tạo một loại Tiền tệ, thì bạn có thể đặt tất cả logic liên quan đến tiền ở đó, bao gồm phương thức ToString () - chính xác, kiểm soát nhiều hơn các giá trị phân tích cú pháp và kiểm soát tốt hơn các phân chia.

Ngoài ra, với lớp Tiền tệ, không có cơ hội vô tình trộn tiền với dữ liệu khác.


10

Một tùy chọn khác (đặc biệt nếu bạn đang lăn lớp của riêng bạn) là sử dụng int hoặc int64 và chỉ định bốn chữ số thấp hơn (hoặc thậm chí là 2) là "bên phải của dấu thập phân". Vì vậy, "trên các cạnh" bạn sẽ cần một số "* 10000" trên đường vào và một số "/ 10000" trên đường ra. Đây là cơ chế lưu trữ được sử dụng bởi Máy chủ SQL của Microsoft, xem http://msdn.microsoft.com/en-au/l Library / ms179882.aspx

Tính chất của điều này là tất cả các tổng của bạn có thể được thực hiện bằng cách sử dụng số học số nguyên (nhanh).


7

Hầu hết các ứng dụng tôi đã làm việc với việc sử dụng decimalđể đại diện cho tiền. Điều này dựa trên giả định rằng ứng dụng sẽ không bao giờ liên quan đến nhiều hơn một loại tiền tệ.

Giả định này có thể dựa trên một giả định khác, rằng ứng dụng sẽ không bao giờ được sử dụng ở các quốc gia khác với các loại tiền tệ khác nhau. Tôi đã thấy những trường hợp được chứng minh là sai.

Bây giờ, giả định đó đang bị thách thức theo một cách mới: Các loại tiền mới như Bitcoin đang trở nên phổ biến hơn và chúng không đặc trưng cho bất kỳ quốc gia nào. Không thực tế rằng một ứng dụng được sử dụng chỉ trong một quốc gia có thể vẫn cần hỗ trợ nhiều loại tiền tệ.

Một số người sẽ nói rằng việc tạo hoặc thậm chí sử dụng một loại chỉ vì tiền là "mạ vàng" hoặc thêm độ phức tạp vượt quá các yêu cầu đã biết. Tôi rất không đồng ý. Một khái niệm càng phổ biến trong miền của bạn, điều quan trọng hơn là phải nỗ lực hợp lý để sử dụng sự trừu tượng hóa chính xác lên phía trước. Nếu bạn muốn thấy sự phức tạp, hãy thử làm việc trong một ứng dụng đã từng sử dụng decimalvà bây giờ có một thuộc tính bổ sung Currencybên cạnh mỗi thuộc decimaltính.

Nếu bạn sử dụng sai trừu tượng lên phía trước, thay thế nó sau sẽ làm việc gấp trăm lần. Điều đó có nghĩa là có khả năng đưa các khiếm khuyết vào mã hiện có và phần tốt nhất là các lỗi đó có thể sẽ liên quan đến số tiền, giao dịch bằng tiền hoặc bất cứ thứ gì có tiền.

Và không khó để sử dụng một cái gì đó ngoài số thập phân. Google "loại tiền nuget" và bạn sẽ thấy rằng nhiều nhà phát triển đã tạo ra những thứ trừu tượng như vậy (bao gồm cả tôi.) Thật dễ dàng. Thật dễ dàng như sử dụng DateTimethay vì lưu trữ một ngày trong một string.


5

Tạo lớp của riêng bạn. Điều này có vẻ kỳ lạ, nhưng một loại .Net không đủ để chi trả cho các loại tiền tệ khác nhau.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.