Tôi nên sử dụng loại dữ liệu nào cho tiền tệ trong trò chơi?


96

Trong một trò chơi mô phỏng kinh doanh đơn giản (được xây dựng bằng Java + Slick2D), số tiền hiện tại của người chơi nên được lưu trữ dưới dạng một floathoặc một int, hoặc một cái gì khác?

Trong trường hợp sử dụng của tôi, hầu hết các giao dịch sẽ sử dụng xu ($ 0,5, $ 1,20, v.v.) và các tính toán lãi suất đơn giản sẽ được tham gia.

Tôi đã thấy mọi người nói rằng bạn không bao giờ nên sử dụng floattiền tệ, cũng như mọi người nói rằng bạn không bao giờ nên sử dụng inttiền tệ. Tôi cảm thấy như tôi nên sử dụng intvà làm tròn mọi tính toán tỷ lệ cần thiết. Tôi nên sử dụng cái gì?


2
Câu hỏi này đã được thảo luận trên StackOverflow. Có vẻ như BigDecimal có lẽ là con đường để đi. stackoverflow.com/questions/285680/ từ
Ade Miller

2
Có phải Java không có Currencykiểu như Delphi's, sử dụng toán học điểm cố định tỷ lệ để cung cấp cho bạn toán thập phân mà không có các vấn đề chính xác vốn có của dấu phẩy động?
Mason Wheeler

1
Đó là trò chơi. Kế toán sẽ không khiến bạn mất một xu và vì vậy những lý do thông thường chống lại việc sử dụng dấu phẩy động cho tiền tệ là không quan trọng.
Loren Pechtel

@MasonWheeler: Java có BigDecimalcác loại vấn đề này.
Martin Schröder

Câu trả lời:


92

Bạn có thể sử dụng int, và xem xét mọi thứ bằng xu. $ 1,20 chỉ là 120 xu. Tại màn hình, bạn đặt số thập phân vào vị trí của nó.

Tính toán lãi suất sẽ được cắt ngắn hoặc làm tròn lên. Vì thế

newAmt = round( 120 cents * 1.04 ) = round( 124.8 ) = 125 cents

Bằng cách này, bạn không có số thập phân lộn xộn luôn luôn dính xung quanh. Bạn có thể trở nên giàu có bằng cách thêm số tiền chưa được tính (do làm tròn số) vào tài khoản ngân hàng của riêng bạn


3
Nếu bạn sử dụng roundkhông có lý do thực sự để bỏ xuống int, có phải không?
sam hocevar

19
+1. Các số dấu phẩy động làm tăng sự so sánh bằng nhau, chúng khó định dạng đúng hơn và đưa ra các lỗi làm tròn hài hước theo thời gian. Tốt hơn là tự mình làm tất cả những thứ đó để bạn không nhận được khiếu nại về nó sau này. Nó thực sự không phải là rất nhiều công việc.
Dobes Vandermeer

+1. Âm thanh như một cách tốt để đi cho trò chơi của tôi. Tôi sẽ tự giải quyết việc làm tròn số int và tránh xa mọi vấn đề nổi.
Lucas Tulio

Chỉ là từ chối trách nhiệm: Tôi đã thay đổi câu trả lời chính xác cho câu hỏi này vì cuối cùng nó là những gì tôi đã sử dụng. Nó đơn giản hơn nhiều và trong bối cảnh của một trò chơi đơn giản như vậy, số thập phân không được tính không thực sự quan trọng.
Lucas Tulio

3
Tuy nhiên, hãy sử dụng Điểm cơ bản chứ không phải Cents (trong đó 100 Điểm cơ bản = 1 xu) với hệ số 10.000 thay vì 100. Điều này được GAAP yêu cầu cho tất cả các ứng dụng Tài chính, Ngân hàng hoặc Kế toán.
Pieter Geerkens

66

Được rồi, tôi sẽ nhảy vào.

Lời khuyên của tôi: đó là một trò chơi. Hãy dễ dàng và sử dụng double.

Đây là lý do của tôi:

  • floatcó một vấn đề chính xác xuất hiện khi thêm đơn vị vào hàng triệu, vì vậy mặc dù nó có thể là lành tính, tôi sẽ tránh loại đó. doublechỉ bắt đầu gặp vấn đề xung quanh các nhóm ngũ cốc (một tỷ tỷ).
  • Vì bạn sẽ có lãi suất, dù sao bạn cũng sẽ cần độ chính xác vô hạn về mặt lý thuyết: với lãi suất 4%, 100 đô la sẽ trở thành 104 đô la, sau đó là 108,16 đô la, sau đó là 112.4864 đô la, v.v ... Điều này làm intlongvô dụng vì bạn không biết dừng lại ở đâu các số thập phân.
  • BigDecimalsẽ cung cấp cho bạn độ chính xác tùy ý nhưng sẽ trở nên chậm chạp một cách đau đớn, trừ khi bạn kẹp độ chính xác vào một lúc nào đó. Các quy tắc làm tròn là gì? Làm thế nào để bạn chọn nơi dừng lại? Có đáng để có nhiều bit chính xác hơn double? Tôi tin là không.

Lý do số học điểm cố định được sử dụng trong các ứng dụng tài chính là bởi vì chúng mang tính quyết định. Các quy tắc làm tròn được xác định hoàn hảo, đôi khi theo luật và phải được áp dụng nghiêm ngặt, nhưng việc làm tròn vẫn xảy ra tại một số điểm. Bất kỳ đối số có lợi cho một loại nhất định dựa trên độ chính xác có khả năng là không có thật. Tất cả các loại có vấn đề chính xác với các loại tính toán bạn sẽ làm.

Ví dụ thực tế

Tôi thấy khá nhiều bình luận khẳng định những điều về làm tròn hoặc độ chính xác mà tôi không đồng ý. Dưới đây là một vài ví dụ bổ sung để minh họa điều tôi muốn nói.

Lưu trữ : nếu đơn vị cơ sở của bạn là cent, có thể bạn sẽ muốn làm tròn đến cent gần nhất khi lưu trữ giá trị:

void SetValue(double v) { m_value = round(v * 100.0) / 100.0; }

Bạn sẽ hoàn toàn không gặp vấn đề làm tròn khi áp dụng phương pháp này mà bạn cũng sẽ không gặp phải với một kiểu số nguyên.

Truy xuất : tất cả các tính toán có thể được thực hiện trực tiếp trên các giá trị kép, không có chuyển đổi:

double value = data.GetValue();
value = value / 3.0 * 12.0;
[...]
data.SetValue(value);

Lưu ý rằng đoạn mã trên không hoạt động nếu bạn thay thế doublevới int64_t: sẽ có một chuyển đổi ngầm để double, sau đó cắt ngắn để int64_t, với một sự mất mát có thể xảy ra information.data.GetValue ()

So sánh : so sánh là một điều cần làm đúng với các kiểu dấu phẩy động. Tôi đề nghị sử dụng một phương pháp so sánh như phương pháp này:

/* Are values equal to a tenth of a cent? */
bool AreCurrencyValuesEqual(double a, double b) { return abs(a - b) < 0.001; }

Làm tròn công bằng

Giả sử bạn có 9,99 đô la trong tài khoản với lãi suất 4%. Người chơi nên kiếm được bao nhiêu? Với làm tròn số nguyên bạn nhận được 0,03 đô la; với làm tròn điểm nổi bạn nhận được 0,04 đô la. Tôi tin rằng sau này là công bằng hơn.


4
+1. Sự làm rõ duy nhất tôi muốn thêm vào, cũng giống như các ứng dụng tài chính tuân thủ các yêu cầu được xác định trước cụ thể, thuật toán làm tròn cũng vậy. Nếu trò chơi là một sòng bạc, nó tuân theo các tiêu chuẩn tương tự và sau đó tăng gấp đôi không phải là một lựa chọn.
Ivaylo Slavov

2
Bạn vẫn phải suy nghĩ về quy tắc làm tròn để định dạng UI. Bởi vì luôn có một bộ phận người chơi sẽ cố coi trò chơi là bảng tính nếu bạn không muốn đối phó với những người nhảy lên và la hét khi họ thấy phần phụ trợ của bạn không sử dụng chính xác như UI của bạn dẫn đến Kết quả 'sai' được hiển thị tùy chọn tốt nhất của bạn để giữ im lặng là sử dụng cùng một biểu diễn bên trong và bên ngoài, có nghĩa là sử dụng định dạng điểm cố định. Trừ khi hiệu suất trở thành một vấn đề BigDecimal là lựa chọn tốt nhất để làm điều này.
Dan Neely

10
Tôi không đồng ý với câu trả lời này. Các vấn đề làm tròn sẽ xuất hiện và nếu chúng giảm xuống và nếu bạn không sử dụng bất kỳ làm tròn bổ sung nào, $ 1 có thể đột nhiên trở thành $ 0,99. Nhưng quan trọng nhất, số thập phân chính xác tùy ý bị chậm là (gần như) hoàn toàn không liên quan. Chúng ta gần như vào năm 2013, và trừ khi bạn thực hiện các yếu tố lớn, công cụ trig hoặc logarit trên vài triệu số với hàng ngàn chữ số, bạn thậm chí sẽ không bao giờ nhận thấy hiệu suất. Dù sao, đơn giản luôn luôn là tốt nhất, vì vậy đề nghị của tôi là lưu trữ tất cả các số dưới dạng xu. Bằng cách đó, tất cả họ đều int_64tlà s.
Panda Pyjama

8
@Sam lần trước tôi đã kiểm tra tài khoản ngân hàng của mình, số dư của tôi không kết thúc bằng .0000000000000001. Các hệ thống tiền tệ thực sự phải hoạt động với các đơn vị không chia được và được thể hiện chính xác bằng các số nguyên. Nếu bạn phải thực hiện phân chia tiền tệ một cách chính xác (điều này thực sự không phổ biến trong thế giới tài chính thực sự), bạn phải thực hiện chúng để tiền không bị mất. Ví dụ 10/3 = 3+3+4hay 10/3 = 3+3+3 (+1). Đối với tất cả các số nguyên hoạt động khác, hoạt động hoàn hảo, không giống như dấu phẩy động có thể gặp các vấn đề làm tròn trong bất kỳ hoạt động nào.
Panda Pyjama

2
@SamHocevar 999 * 4/100. Trường hợp không được quy định bởi quy định giả định tất cả làm tròn sẽ được thực hiện trong các ngân hàng ủng hộ.
Dan Neely

21

Các loại dấu phẩy động trong Java ( float, double) không phải là đại diện tốt cho tiền tệ vì một lý do chính - có lỗi máy khi làm tròn. Thậm chí nếu một phép tính đơn giản trả về một số nguyên - như 12.0/2(6.0), điểm nổi sức mạnh sai tròn nó (do tho đại diện cụ thể của các loại trong bộ nhớ) như 6.0000000000001hoặc 5.999999999999998hoặc tương đương. Đây là kết quả của việc làm tròn máy cụ thể xảy ra trong bộ xử lý và nó là duy nhất cho máy tính đã tính toán nó. Thông thường, hiếm khi xảy ra sự cố khi vận hành với các giá trị này, vì lỗi này khá sơ suất, nhưng thật khó để hiển thị điều đó cho người dùng.

Một giải pháp khả thi cho vấn đề này là sử dụng một triển khai tùy chỉnh kiểu dữ liệu dấu phẩy động, như BigDecimal. Nó hỗ trợ các cơ chế tính toán tốt hơn, ít nhất là cách ly các lỗi làm tròn không phải là máy cụ thể, nhưng chậm hơn về mặt hiệu suất.

Nếu bạn cần năng suất cao, tốt hơn bạn nên sử dụng các loại đơn giản. Trong trường hợp bạn hoạt động với dữ liệu tài chính quan trọngmỗi xu đều quan trọng (như ứng dụng Forex, hoặc một số trò chơi sòng bạc) thì tôi khuyên bạn nên sử dụng Longhoặc long. Longsẽ cho phép bạn xử lý số lượng lớn và độ chính xác tốt. Giả sử bạn cần, giả sử, 4 chữ số sau dấu thập phân, tất cả những gì bạn cần là nhân số tiền với 10000. Có kinh nghiệm trong việc phát triển các trò chơi sòng bạc trực tuyến, tôi thường thấy Longđược sử dụng để đại diện cho tiền bằng xu . Trong các ứng dụng Forex, độ chính xác là quan trọng hơn, vì vậy bạn sẽ cần số nhân lớn hơn - tuy nhiên, toàn bộ số không có vấn đề làm tròn máy (tất nhiên là làm tròn thủ công như trong 3/2 bạn nên tự xử lý).

Một tùy chọn có thể chấp nhận sẽ là sử dụng các loại dấu phẩy động tiêu chuẩn - FloatDouble, nếu hiệu suất quan trọng hơn độ chính xác đến hàng trăm phần trăm. Sau đó, trên logic hiển thị của bạn, tất cả những gì bạn cần là sử dụng định dạng được xác định trước , để sự xấu xí của việc làm tròn máy tiềm năng không đến với người dùng.


4
+1 Một chi tiết: "Giả sử bạn cần, giả sử, 4 chữ số sau dấu thập phân, tất cả những gì bạn cần là nhân số tiền với 1000." -> Đây được gọi là điểm cố định.
Laurent Couvidou

1
@Sam, những con số đã được cung cấp cho cổ phần mẫu. Tuy nhiên, cá nhân tôi đã thấy kết quả kỳ lạ với những con số đơn giản như vậy, nhưng đó không phải là một kịch bản thường xuyên. Khi các điểm nổi đến chơi, điều này có thể xảy ra nhiều hơn, nhưng khó có thể phát hiện hơn
Ivaylo Slavov

2
@Ivaylo Slavov, tôi đồng ý với bạn. Trong câu trả lời của tôi, tôi chỉ đưa ra ý kiến ​​của mình. Tôi thích thảo luận và sẵn sàng nhận điều đúng đắn. Cũng cảm ơn ý kiến ​​của bạn. :)
Md Mahbubur Rahman

1
@SamHocevar: Lý do đó không hoạt động trong mọi trường hợp. Xem: ideone.com/nI2ZOK
Samaursa

1
@SamHocevar: Điều đó cũng không được đảm bảo. Các số trong phạm vi vẫn là toàn bộ số bắt đầu tích lũy lỗi trên bộ phận đầu tiên: ideone.com/AKbR7i
Samaursa

17

Đối với trò chơi quy mô nhỏ và tốc độ xử lý, bộ nhớ là vấn đề quan trọng (do độ chính xác hoặc làm việc với bộ đồng xử lý toán học có thể làm chậm một cách đau đớn), có gấp đôi là đủ.

Nhưng đối với các trò chơi quy mô lớn (ví dụ: trò chơi xã hội) và khi tốc độ xử lý, bộ nhớ không bị giới hạn, ở đó BigDecimal sẽ tốt hơn. Bởi vì ở đây,

  • int hoặc dài để tính toán tiền tệ.
  • phao và đôi không thể đại diện chính xác cho hầu hết 10 số thực.

Tài nguyên:

Từ https://stackoverflow.com/questions/3730019/why-not-use-double-or-float-to-interesent-currency

Bởi vì số float và double không thể đại diện chính xác cho hầu hết 10 số thực.

Đây là cách một số dấu phẩy động của IEEE-754 hoạt động: nó dành một chút cho dấu hiệu, một vài bit để lưu trữ số mũ và phần còn lại cho phân số thực tế. Điều này dẫn đến các số được biểu diễn dưới dạng tương tự như 1,45 * 10 ^ 4; ngoại trừ thay vì cơ sở là 10, thì đó là hai.

Trên thực tế, tất cả các số thập phân thực có thể được xem là phân số chính xác của lũy thừa mười. Chẳng hạn, 10,45 thực sự là 1045/10 ^ 2. Và cũng giống như một số phân số không thể được biểu diễn chính xác như một phần của sức mạnh mười (1/3 đến trong tâm trí), một số trong số chúng cũng không thể được biểu diễn chính xác như một phần của sức mạnh của hai. Một ví dụ đơn giản, bạn chỉ đơn giản là không thể lưu trữ 0,1 bên trong một biến dấu phẩy động. Bạn sẽ nhận được giá trị đại diện gần nhất, tương đương với 0,0999999999999999996 và phần mềm sẽ làm tròn nó thành 0,1 khi hiển thị nó.

Tuy nhiên, khi bạn thực hiện nhiều phép cộng, phép trừ, phép nhân và phép chia trên các số không chính xác, bạn sẽ mất nhiều hơn và chính xác hơn khi các lỗi nhỏ xuất hiện. Điều này làm cho số float và double không đủ để xử lý tiền, trong đó yêu cầu độ chính xác hoàn hảo.

Từ Bloch, J., Java hiệu quả, tái bản lần 2, Mục 48:

The float and double types are particularly ill-suited for 

tính toán tiền tệ vì không thể biểu thị 0,1 (hoặc bất kỳ công suất âm nào khác của mười) dưới dạng nổi hoặc gấp đôi chính xác.

For example, suppose you have $1.03 and you spend 42c. How much money do you have left?

System.out.println(1.03 - .42);

prints out 0.6100000000000001.

The right way to solve this problem is to use BigDecimal, 

int hoặc dài để tính toán tiền tệ.

Cũng có một cái nhìn vào


Tôi chỉ không đồng ý với phần dài phù hợp với các tính toán nhỏ. Theo kinh nghiệm thực tế của tôi, nó đã được chứng minh đủ để xử lý độ chính xác tốt và số tiền lớn. Đúng, nó có thể hơi cồng kềnh khi sử dụng nhưng nó đánh bại BigDecimal ở hai điểm quan trọng - 1) nó nhanh hơn (BigDecimal sử dụng làm tròn phần mềm, chậm hơn so với làm tròn CPU tích hợp được sử dụng trong float / double) và 2) BigDecimal khó tồn tại hơn trong cơ sở dữ liệu mà không mất độ chính xác - không phải tất cả các cơ sở dữ liệu đều hỗ trợ loại 'tùy chỉnh' như vậy. Long nổi tiếng và được hỗ trợ rộng rãi trên tất cả các cơ sở dữ liệu chính.
Ivaylo Slavov

@Ivaylo Slavov, Xin lỗi vì lỗi của tôi. Tôi đã cập nhật câu trả lời của tôi.
Md Mahbubur Rahman

Không cần lời xin lỗi để đưa ra một cách tiếp cận khác cho cùng một vấn đề :)
Ivaylo Slavov

2
@Ivaylo Slavov, tôi đồng ý với bạn. Trong câu trả lời của tôi, tôi chỉ đưa ra ý kiến ​​của mình. Tôi thích thảo luận và sẵn sàng nhận điều đúng đắn. Cũng cảm ơn ý kiến ​​của bạn. :)
Md Mahbubur Rahman

Mục đích của trang này là làm rõ các vấn đề và giúp OP đưa ra quyết định đúng đắn, tùy thuộc vào kịch bản cụ thể. Tất cả những gì chúng ta có thể làm là giúp tăng tốc quá trình :)
Ivaylo Slavov

13

Bạn muốn lưu trữ tiền tệ của bạn longtính toán tiền tệ của bạn double, ít nhất là một bản sao lưu. Bạn muốn tất cả các giao dịch diễn ra như long.

Lý do bạn muốn lưu trữ tiền tệ của mình longlà vì bạn không muốn mất bất kỳ loại tiền nào.

Giả sử bạn sử dụng một double, và bạn không có tiền. Ai đó cho bạn ba xu, và sau đó đưa họ trở lại.

You:       0.1+0.1+0.1-0.1-0.1-0.1 = 2.7755575615628914E-17

Chà, điều đó không tuyệt lắm. Có thể ai đó có 10 đô la muốn cho tài sản của họ đi bằng cách trước tiên đưa cho bạn ba xu, sau đó đưa 9,70 đô la cho người khác.

Them: 10.0-0.1-0.1-0.1-9.7 = 1.7763568394002505E-15

Và sau đó bạn cung cấp cho họ các xu trở lại:

Them: ...+0.1+0.1+0.1 = 0.3000000000000018

Đây chỉ là hỏng.

Bây giờ, chúng ta hãy sử dụng lâu dài và chúng ta sẽ theo dõi một phần mười xu (vì vậy 1 = 0,001 đô la). Chúng ta hãy cho mọi người trên hành tinh một tỷ, một trăm mười hai triệu, bảy mươi lăm nghìn, một trăm bốn mươi ba đô la:

Us: 7000000000L*1112075143000L = 1 894 569 218 048

Ừm, chờ đã, chúng tôi có thể cho mọi người hơn một tỷ đô la, và chỉ chi tiêu ít hơn hai? Tràn ngập là một thảm họa ở đây.

Vì vậy, bất cứ khi nào bạn tính toán một số tiền để chuyển, hãy sử dụng doubleMath.roundđể nhận được long. Sau đó sửa chữa số dư (cộng và trừ cả hai tài khoản) bằng cách sử dụng long.

Nền kinh tế của bạn sẽ không bị rò rỉ, và nó sẽ mở rộng lên tới một triệu đô la.

Có nhiều vấn đề phức tạp hơn - ví dụ: bạn sẽ làm gì nếu bạn thực hiện hai mươi khoản thanh toán? * - nhưng điều này sẽ giúp bạn bắt đầu.

* Bạn tính toán một khoản thanh toán là gì, làm tròn đến long; sau đó nhân lên 20.0và kiểm tra xem nó nằm trong phạm vi; nếu vậy, bạn nhân số tiền thanh toán 20Lvới số tiền được khấu trừ từ số dư của bạn. Nói chung, tất cả các giao dịch phải được xử lý như long, vì vậy bạn thực sự cần phải tổng hợp tất cả các giao dịch riêng lẻ; bạn có thể nhân như một phím tắt, nhưng bạn cần đảm bảo rằng bạn không thêm các lỗi làm tròn bạn không bị tràn, điều đó có nghĩa là bạn cần kiểm tra doubletrước khi thực hiện phép tính thực long.


8

Tôi muốn nói rằng bất kỳ giá trị nào có thể được hiển thị cho người dùng hầu như luôn luôn là một số nguyên. Tiền chỉ là ví dụ nổi bật nhất về điều này. Xử lý 225 sát thương bốn lần cho một con quái vật với 900 HP và phát hiện ra rằng nó vẫn còn 1 HP sẽ trừ đi trải nghiệm cũng giống như phát hiện ra rằng bạn là một phần vô hình của một xu thiếu một thứ gì đó.

Về mặt kỹ thuật hơn, tôi nghĩ rằng đáng chú ý rằng người ta không cần phải quay trở lại phao để làm những thứ tiên tiến như sở thích. Miễn là bạn đã có đủ khoảng trống trong kiểu số nguyên đã chọn, một phép nhân và một phép chia sẽ được nhân cho một số thập phân, ví dụ để thêm 4%, làm tròn xuống:

number=(number*104)/100

Để thêm 4%, làm tròn theo quy ước tiêu chuẩn:

number=(number*104+50)/100

Không có điểm nổi không chính xác ở đây, làm tròn luôn phân chia chính xác trên .5nhãn hiệu.

Chỉnh sửa, câu hỏi thực sự:

Thấy thế nào các cuộc tranh luận đã đi Tôi bắt đầu suy nghĩ rằng phác thảo những gì câu hỏi là tất cả về thể có nhiều hữu ích hơn là một đơn giản int/ floatcâu trả lời. Cốt lõi của câu hỏi không phải là về các loại dữ liệu, mà là kiểm soát các chi tiết của một chương trình.

Sử dụng một số nguyên để biểu thị một giá trị không nguyên buộc người lập trình phải xử lý các chi tiết thực hiện. "Độ chính xác để sử dụng?" và "Cách nào để làm tròn?" là những câu hỏi phải được trả lời rõ ràng.

Mặt khác, một dấu phẩy không buộc lập trình viên phải lo lắng, nó đã làm gần như những gì người ta mong đợi. Nhưng vì một số float không phải là độ chính xác vô hạn, một số phép làm tròn sẽ diễn ra và việc làm tròn đó là không thể đoán trước được.

Điều gì xảy ra trong một lần sử dụng phao và muốn kiểm soát việc làm tròn? Hóa ra là gần như không thể. Cách duy nhất để làm cho một float thực sự có thể dự đoán được là chỉ sử dụng các giá trị có thể được biểu diễn trong toàn bộ 2^ns. Nhưng việc xây dựng đó làm cho phao khá khó sử dụng.

Do đó, câu trả lời cho câu hỏi đơn giản là: Nếu bạn muốn kiểm soát, hãy sử dụng số nguyên, nếu không, hãy sử dụng số float.

Nhưng câu hỏi đang được tranh luận chỉ là một dạng khác của câu hỏi: Bạn có muốn kiểm soát không?


5

Ngay cả khi đó là "chỉ là một trò chơi", tôi sẽ sử dụng Mô hình tiền từ Martin Fowler, được hỗ trợ từ lâu.

Tại sao?

Bản địa hóa (L10n): Sử dụng mẫu đó bạn có thể dễ dàng bản địa hóa loại tiền trong trò chơi của mình. Hãy nghĩ về những trò chơi của ông trùm cũ như "Transport Tycoon". Họ dễ dàng cho phép người chơi đổi tiền trong trò chơi (ví dụ: Từ Bảng Anh sang Đô la Mỹ) để đáp ứng tiền tệ trong thế giới thực.

Kiểu dữ liệu dài là số nguyên bổ sung hai chữ ký 64 bit. Nó có giá trị tối thiểu là -9,223,372,036,854,775,809 và giá trị tối đa là 9,223,372,036,854,775,807 (đã bao gồm) ( Hướng dẫn Java )

Điều đó có nghĩa là bạn có thể lưu trữ 9.000 lần Cung tiền M2 US hiện tại (~ 10.000 tỷ đô la). Cung cấp cho bạn đủ chỗ để sử dụng bất kỳ loại tiền tệ nào khác trên thế giới, có thể, ngay cả những người đã / đang siêu lạm phát (Nếu tò mò, hãy xem lạm phát của Đức sau Thế chiến , trong đó 1 pound bánh mì là 3.000.000.000 điểm)

Long rất dễ tồn tại, rất nhanh và sẽ cung cấp cho bạn đủ chỗ để thực hiện tất cả các tính toán quan tâm chỉ bằng số nguyên học, câu trả lời của eBusiness đưa ra lời giải thích về cách thực hiện điều đó.


2

Bao nhiêu công việc bạn muốn đưa vào này? Độ chính xác quan trọng như thế nào? Bạn có quan tâm đến việc theo dõi các lỗi phân số xảy ra với làm tròn và sự thiếu chính xác trong việc biểu diễn các số thập phân trong một hệ thống nhị phân không?

Cuối cùng, tôi có xu hướng dành nhiều thời gian hơn cho việc mã hóa và thực hiện các bài kiểm tra đơn vị cho "các trường hợp góc" và các trường hợp có vấn đề đã biết - vì vậy tôi sẽ suy nghĩ về một BigInteger đã sửa đổi, bao gồm số lượng lớn tùy ý và duy trì các bit phân số bằng BigDecimal hoặc một phần BigRational (hai BigIntegers, một cho mẫu số và một cho tử số) - và bao gồm mã để giữ cho phần phân số một phần thực tế bằng cách (có lẽ chỉ định kỳ) thêm bất kỳ phần không phân đoạn nào vào BigInteger chính. Sau đó, tôi sẽ theo dõi nội bộ mọi thứ bằng xu chỉ để giữ các phần phân số ra khỏi các tính toán GUI.

Có lẽ cách phức tạp cho một trò chơi (đơn giản) - nhưng tốt cho một thư viện được xuất bản dưới dạng nguồn mở! Chỉ cần tìm ra các cách để giữ hiệu suất tốt khi xử lý các bit phân số ...


1

Chắc chắn không nổi. Chỉ với 7 chữ số, bạn chỉ có độ chính xác như:

12.345,67 123,456,7x

Vì vậy, bạn thấy, với 10 ^ 5 đô la, bạn đang mất dấu xu. gấp đôi có thể sử dụng cho mục đích trò chơi, không phải trong cuộc sống thực vì những lo ngại chính xác.

Nhưng dài (và điều này có nghĩa là 64 bit, hoặc dài trong C ++) là không đủ nếu bạn sẽ theo dõi các giao dịch và tổng hợp chúng. Nó đủ để duy trì tỷ lệ nắm giữ ròng của bất kỳ công ty nào, nhưng tất cả các giao dịch trong một năm có thể bị tràn. Điều đó phụ thuộc vào "thế giới" tài chính của bạn lớn như thế nào trong trò chơi.


0

Một giải pháp khác tôi sẽ thêm vào đây là kiếm một lớp tiền. Lớp học sẽ là một cái gì đó giống như (thậm chí có thể chỉ là một cấu trúc).

class Money
{
     string currencyType; //the type of currency example USD could be an enum as well
     bool isNegativeValue;
     unsigned long int wholeUnits;
     unsigned short int partialUnits;
}

Điều này sẽ cho phép bạn biểu thị số xu trong trường hợp này dưới dạng số nguyên và toàn bộ đô la dưới dạng số nguyên. Vì bạn có một cờ riêng cho âm, nên bạn có thể sử dụng số nguyên không dấu cho các giá trị của mình để nhân đôi số tiền có thể (bạn cũng có thể viết một lớp số áp dụng ý tưởng này cho các số để có được số thực lớn). Tất cả những gì bạn cần làm là quá tải toán tử toán học và bạn có thể sử dụng nó giống như bất kỳ kiểu dữ liệu cũ nào. Nó chiếm nhiều bộ nhớ hơn, nhưng nó thực sự mở rộng giới hạn giá trị.

Điều này có thể được mở rộng hơn nữa để bao gồm những thứ như số đơn vị một phần trên toàn bộ đơn vị để bạn có thể có các loại tiền chia nhỏ hơn 100 đơn vị phụ, trong trường hợp này, mỗi đô la. Bạn có thể có 125 phao tạo thành một flooper chẳng hạn.

Biên tập:

Tôi sẽ mở rộng ý tưởng rằng bạn cũng có thể có một bảng tra cứu, rằng loại tiền có thể truy cập sẽ cung cấp tỷ giá hối đoái cho loại tiền tệ này so với tất cả các loại tiền tệ khác. Bạn có thể xây dựng điều này vào các hàm quá tải toán tử của bạn. Do đó, nếu bạn tự động cố gắng thêm 4 USD vào 4 bảng Anh, nó sẽ tự động cung cấp cho bạn 6,6 bảng (khi viết).


0

Như đã đề cập trong một trong những nhận xét về câu hỏi ban đầu của bạn, vấn đề này đã được đề cập trên StackExchange: https://stackoverflow.com/questions/8148684/what-is-the-best-data-type-to-use-for- tiền trong ứng dụng java

Về cơ bản, các loại dấu phẩy động không bao giờ được sử dụng để thể hiện các loại tiền tệ và giống như hầu hết các ngôn ngữ Java có loại phù hợp hơn. Tài liệu riêng của Oracle về người nguyên thủy đề nghị sử dụng BigDecimal .


-1

Sử dụng lớp học đó là cách tốt nhất. Bạn có thể ẩn việc thực hiện số tiền của mình, bạn có thể chuyển gấp đôi / lâu những gì bạn muốn bất cứ lúc nào.

Thí dụ

class Money
{
    private long count;//Store here what ever you want in what type you want i suggest long or int
    //methods constructors etc.
    public String print()
    {
        return count/100.F; //convert this to string
    }
}

Trong mã của bạn, chỉ cần sử dụng getter, đó là cách tốt hơn tôi nghĩ và bạn có thể lưu trữ các phương thức hữu ích hơn.

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.