2009-03-01 30 views
9

Tôi đã đọc một vài bài viết về các nguy cơ của một số loại dữ liệu nhất định được sử dụng để lưu trữ số tiền. Thật không may, một số khái niệm không nằm trong vùng thoải mái của tôi.Thực tiễn tốt nhất để xử lý số tiền trong C#

Sau khi đọc các bài viết này, các phương pháp và khuyến nghị tốt nhất để làm việc với tiền trong C# là gì? Tôi có nên sử dụng một loại dữ liệu nhất định cho một số lượng nhỏ và một loại dữ liệu khác với số tiền lớn hơn không? Ngoài ra, tôi có trụ sở tại Vương quốc Anh có nghĩa là chúng tôi sử dụng, (ví dụ: 4.000 bảng, trong khi các nền văn hóa khác đại diện cho cùng một số tiền khác nhau).

Trả lời

8

Bạn không nên sử dụng số dấu phẩy động do lỗi làm tròn. Loại thập phân phải phù hợp với bạn.

+0

Tôi rất tò mò muốn biết lý do người nào đó bỏ phiếu này. –

+0

Tôi đã bỏ phiếu chỉ để bù lại phiếu bầu xuống. Tôi không nghĩ rằng phiếu giảm giá nên được cho phép mà không có một bình luận. –

2

Tôi sử dụng đối tượng giá trị để giữ cả số tiền (dưới dạng decimal) và đơn vị tiền tệ. Điều này cho phép làm việc với các loại tiền tệ khác nhau cùng một lúc. decimal là loại dữ liệu đề xuất cho tiền trong .NET.

16

Thập phân là loại hợp lý nhất cho số tiền.

Thập phân là một điểm số cơ bản 10 kiểu số có 28 chữ số thập phân chính xác. Sử dụng thập phân, bạn sẽ có ít bất ngờ hơn bạn sẽ sử dụng cơ sở 2 loại đôi.

Sử dụng một nửa bộ nhớ nhiều như Decimal và Double sẽ nhanh hơn nhiều vì phần cứng CPU cho nhiều hoạt động điểm nổi phổ biến, nhưng nó không thể đại diện cho hầu hết 10 phân số cơ bản (như 1.05) chính xác và kém chính xác hơn 15 + số thập phân chính xác. Đôi không có lợi thế của nhiều hơn (nó có thể đại diện cho số lượng lớn hơn và nhỏ hơn) mà có thể có ích cho một số tính toán, đặc biệt là một số tính toán thống kê.

Một câu trả lời cho câu hỏi của bạn cho biết rằng Thập phân là điểm cố định với 4 chữ số thập phân. Đây không phải là trường hợp. Nếu bạn nghi ngờ điều này, nhận thấy rằng các dòng mã sau đây mang lại 0,0000000001:

Console.WriteLine("number={0}", 1m/10000000000m); 

Có nói tất cả điều đó, nó là thú vị để lưu ý rằng phần mềm được sử dụng rộng rãi nhất trên thế giới để làm việc với một lượng tiền tệ, Microsoft Excel , sử dụng tăng gấp đôi. Tất nhiên, họ phải nhảy qua rất nhiều vòng để làm cho nó hoạt động tốt, và nó vẫn để lại một cái gì đó để được mong muốn. Hãy thử hai công thức trong Excel:

  • = 1-0.9-0.1
  • = (1-0.9-0.1)

Lợi suất đầu tiên 0, sản lượng thứ hai ~ -2.77e-17 . Excel thực sự xoa bóp các con số khi cộng và trừ số trong một số trường hợp, nhưng không phải trong mọi trường hợp.

+0

Ví dụ về Neat Excel! –

+0

Thập phân cho tiền là tốt. Nhưng tỷ lệ tiền vẫn phải gấp đôi (ví dụ: lãi suất). – Richard

6

Martin Fowler khuyên bạn nên sử dụng Money class. Xem liên kết cho lý do. Có một số cách triển khai ý tưởng của anh ấy ở đó, hoặc bạn có thể viết ý tưởng của riêng mình. Việc thực hiện riêng của Fowler là trong Java, vì vậy anh ta sử dụng một lớp. Các phiên bản C# tôi đã thấy sử dụng một cấu trúc, có vẻ hợp lý.

0

Đề xuất của tôi sẽ là sử dụng Thập phân, như được khuyến nghị bởi những người khác nếu cần phân chia. Đối với ứng dụng kiểm đếm đơn giản, tôi muốn giới thiệu một loại Integer. Đối với cả hai loại, tôi sẽ luôn luôn làm việc trên mệnh giá tiền tệ thấp nhất. (ví dụ: xu ở Canada/Hoa Kỳ)

Tôi thích lý thuyết về cuộc gọi Tiền của Fowler được thêm bởi @dangph.

0

Dù bạn làm gì, hãy đảm bảo rằng bạn hiểu cách xử lý số tiền tệ trong mỗi cấp trong đơn đăng ký của mình.

Tôi đã từng theo dõi tuần theo dõi lỗi 1 because vì SQLServer và .Net sử dụng các cách khác nhau làm tròn tiền tệ và ứng dụng không nhất quán trong cách xử lý các loại tính toán nhất định - đôi khi chúng được thực hiện trong SQL, đôi khi trong lưới. Nhìn vào "bankers' rounding" nếu bạn quan tâm.

Ngoài ra còn có các vấn đề liên quan đến định dạng tiền tệ - không chắc chắn bạn phải đối phó với số tiền không phải của Vương quốc Anh, các ngôn ngữ/nền văn hóa khác, v.v.

+0

Một vấn đề khác cần lưu ý là SQL Server lưu trữ DATETIME với độ chính xác 3.33 mili giây (0. 00333 giây). Tôi một lần có chút bởi điều này vì nó không đủ cho các mục đích của tôi. – ahsteele

0

Như bạn đã nêu trong câu hỏi của mình ngoài việc sử dụng loại dữ liệu thích hợp, chương trình của bạn sẽ xử lý chuyển đổi tiền tệ như thế nào là quan trọng. Vấn đề này tất nhiên nếu không độc quyền với tiền tệ. Jeff Atwood đã làm một bài viết tuyệt vời tóm tắt các nhân đức thực hiện The Turkey Test.

Các vấn đề liên quan