2010-04-02 63 views
51

Tôi tò mò cái nào sẽ phù hợp hơn với trường tiền tệ? Tôi sẽ thực hiện các hoạt động đơn giản như lấy sự khác biệt, tỷ lệ phần trăm giữa giá cũ và giá mới. Tôi dự định giữ hai chữ số sau số 0 (nghĩa là 10,50) và phần lớn thời gian nếu các chữ số này bằng 0, tôi sẽ ẩn các số này và hiển thị số "10"Django: FloatField hoặc DecimalField cho tiền tệ?

ps: Tiền tệ KHÔNG phải là đô la dựa :)

Trả lời

89

Luôn sử dụng DecimalField để kiếm tiền. Ngay cả hoạt động đơn giản (cộng, trừ) không được miễn dịch nổi các vấn đề làm tròn:

>>> 10.50 - 0.20 
10.300000000000001 

>>> Decimal('10.50') - Decimal('0.20') 
Decimal('10.30') 
+4

'>>> 10.50 - 0.20' trong Python 2.7 nhận' 10.3'. – Rockallite

+0

Welp, crap. Tôi sẽ di chuyển rất nhiều dữ liệu ra khỏi lĩnh vực FloatField/cột của tôi để DecimalField ... – teewuane

+0

Thời gian cao, chúng tôi có một "không sử dụng điểm nổi cho tiền" tương tự như của bobince http://stackoverflow.com/a/1732454/ 604511 – aitchnyu

6

chỉnh sửa: Dự án Satchmo không còn hoạt động, vì vậy hãy xem xét những lựa chọn thay thế để xử lý tệ


Sốdựa trên Django có một CurrencyField và CurrencyWidget đáng để xem xét.

Kiểm tra thư mục satchmo_utils ứng dụng cho nguồn

32

Câu trả lời cho câu hỏi là đúng, tuy nhiên một số người dùng sẽ vấp ngã về câu hỏi này để tìm hiểu sự khác biệt giữa DecimalField và FloatField. Vấn đề làm tròn nổi Seth mang đến là một vấn đề đối với tiền tệ.

Các Documents Hoa Django

The FloatField class is sometimes mixed up with the DecimalField class. Although they both represent real numbers, they represent those numbers differently. FloatField uses Python’s float type internally, while DecimalField uses Python’s Decimal type. Read more here .

Dưới đây là sự khác biệt khác giữa hai lĩnh vực:

DecimalField:

  • DecimalFields phải xác định một 'decimal_places' và một thuộc tính 'max_digits'.
  • Bạn nhận được hai xác nhận biểu mẫu miễn phí ở đây từ các thuộc tính bắt buộc ở trên, ví dụ: Nếu bạn đặt max_digits thành 4 và nhập số thập phân là 4.00000 (5 chữ số), bạn sẽ gặp lỗi này: Đảm bảo không có tổng cộng hơn 4 chữ số.
  • Bạn cũng nhận được xác thực biểu mẫu tương tự được thực hiện cho các vị trí thập phân (mà trong hầu hết các trình duyệt cũng sẽ xác thực trên giao diện người dùng bằng thuộc tính bước trên trường nhập. Nếu bạn đặt decimal_places = 1 và nhập 0,001 làm giá trị bạn sẽ nhận được một lỗi rằng giá trị tối thiểu phải là 0.1.
  • Returns một decimal.Decimal, gõ là
  • không có xác nhận thêm như DecimalField
  • với một kiểu Decimal, làm tròn cũng được xử lý cho bạn do các thuộc tính bắt buộc cần được đặt như mô tả ở trên. Vì vậy, từ trình bao, nếu bạn
  • Trong cơ sở dữ liệu (postgresql), DecimalField sẽ được lưu d dưới dạng số (max_digits, decimal_laces) Loại và Bộ nhớ được đặt là "chính", từ ví dụ trên, Loại là số (4,1)

Thông tin thêm về DecimalField from the Django Docs.

FloatField:

  • Trả về xây dựng trong kiểu float,
  • Không làm tròn thông minh, và thực sự có thể gây ra các vấn đề làm tròn như được mô tả trong câu trả lời Seths.
  • Không có hình thức xác nhận thêm rằng bạn nhận được từ DecimalField
  • Trong cơ sở dữ liệu (postgresql), các FloatField được lưu như là một "chính xác kép" Type, và lưu trữ được thiết lập là "đồng bằng"

Thông tin thêm về FloatField from the Django Docs.

Áp dụng cho cả hai:

  • Cả hai lĩnh vực mở rộng từ lớp "Field" và có thể chấp nhận 'trống',, 'name' 'null', 'verbose_name', 'primary_key', 'max_length', 'duy nhất', 'db_index', 'rel', 'mặc định', 'có thể chỉnh sửa', 'serialize', 'unique_for_date', 'unique_for_month', 'unique_for_year', 'choice', 'help_text', 'db_column', 'db_tablespace Thuộc tính ',' auto_created ',' validators ',' error_messages ', vì tất cả các Trường mở rộng từ "Trường" sẽ có.
  • Tiện ích biểu mẫu mặc định cho cả hai trường là TextInput.

Tôi đã xem qua câu hỏi này khi tìm kiếm sự khác biệt giữa hai lĩnh vực vì vậy tôi nghĩ rằng điều này sẽ giúp những người trong hoàn cảnh tương tự :)

UPDATE: Để trả lời câu hỏi, tôi nghĩ bạn có thể lấy đi với một trong hai để đại diện cho tiền tệ, mặc dù thập phân là một phù hợp tốt hơn nhiều. Có một vấn đề làm tròn khi nó được tính cho phao, do đó bạn phải sử dụng round(value, 2) để giữ cho biểu diễn phao của bạn được làm tròn đến hai chữ số thập phân. Dưới đây là ví dụ nhanh:

>>> round(1.13 * 50 + .01, 2) 
56.51 

Bạn vẫn có thể gặp rắc rối với phao và tròn. Giống như ở đây chúng tôi nhìn thấy nó làm tròn xuống trên một giá trị 5:

>>> round(5.685, 2) 
5.68 

Nhưng trong trường hợp này, nó sẽ làm tròn lên:

>>> round(2.995, 2) 
3.0 

Nó có tất cả để làm với cách phao được lưu trữ trong bộ nhớ . Xem here.

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