Jenis data apa yang harus saya gunakan untuk mata uang dalam game?


96

Dalam permainan simulasi bisnis sederhana (dibangun di Java + Slick2D), haruskah jumlah uang pemain saat ini disimpan sebagai floatatau int, atau sesuatu yang lain?

Dalam kasus penggunaan saya, sebagian besar transaksi akan menggunakan sen ($ 0,50, $ 1,20, dll), dan perhitungan suku bunga sederhana akan terlibat.

Saya telah melihat orang-orang mengatakan Anda tidak boleh menggunakan floatmata uang, serta orang-orang mengatakan Anda tidak boleh menggunakan intmata uang. Saya merasa harus menggunakan intdan menyelesaikan perhitungan persentase yang diperlukan. Apa yang harus saya gunakan?


2
Pertanyaan ini dibahas di StackOverflow. Sepertinya BigDecimal mungkin adalah cara yang harus dilakukan. stackoverflow.com/questions/285680/…
Ade Miller

2
Apakah Java tidak memiliki Currencytipe seperti Delphi, yang menggunakan matematika titik tetap skala untuk memberi Anda matematika desimal tanpa masalah presisi yang melekat pada titik mengambang?
Mason Wheeler

1
Itu adalah game. Akuntansi tidak akan mengikat Anda untuk penny rounded off dan karenanya alasan normal untuk menggunakan floating point untuk mata uang tidak masalah.
Loren Pechtel

@MasonWheeler: Java memiliki BigDecimalmasalah seperti ini.
Martin Schröder

Jawaban:


92

Anda dapat menggunakan int, dan mempertimbangkan semuanya dalam sen. $ 1,20 hanya 120 sen. Pada layar, Anda meletakkan desimal di tempatnya.

Perhitungan bunga hanya akan dipotong atau dibulatkan. Begitu

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

Dengan cara ini, Anda tidak memiliki desimal acak yang selalu menempel. Anda bisa menjadi kaya dengan menambahkan uang yang tidak terhitung (karena pembulatan) ke dalam rekening bank Anda sendiri


3
Jika Anda menggunakan roundtidak ada alasan nyata untuk dilemparkan int, bukan?
sam hocevar

19
+1. Angka floating point mengacaukan perbandingan kesetaraan, mereka lebih sulit untuk memformat dengan benar, dan memperkenalkan kesalahan pembulatan lucu seiring waktu. Lebih baik melakukan semua hal itu sendiri sehingga Anda tidak mendapatkan keluhan tentang hal itu nanti. Ini sebenarnya tidak banyak pekerjaan.
Dobes Vandermeer

+1. Kedengarannya seperti cara yang baik untuk permainan saya. Saya akan berurusan dengan membulatkan ints sendiri dan menjauh dari semua masalah float.
Lucas Tulio

Hanya penafian: Saya mengubah jawaban yang benar untuk ini karena akhirnya menjadi apa yang saya gunakan. Ini jauh lebih sederhana dan dalam konteks gim yang begitu sederhana, desimal yang tidak terhitung tidak terlalu penting.
Lucas Tulio

3
Namun, gunakan Basis Points bukan Cents (di mana 100 Basis Points = 1 sen) dengan faktor 10.000 bukannya 100. Ini diperlukan oleh GAAP untuk semua aplikasi Keuangan, Perbankan atau Akuntansi.
Pieter Geerkens

66

Oke, saya akan melompat.

Saran saya: ini permainan. Tenang dan gunakan double.

Inilah alasan saya:

  • floatmemang memiliki masalah presisi yang muncul ketika menambahkan unit ke jutaan, jadi meskipun mungkin jinak, saya akan menghindari tipe itu. doublehanya mulai mendapatkan masalah di sekitar kuintillon (satu miliar miliar).
  • Karena Anda akan memiliki suku bunga, Anda akan memerlukan ketepatan teoretis tak terbatas: dengan suku bunga 4%, $ 100 akan menjadi $ 104, lalu $ 108,16, lalu $ 112,4864, dll. Ini membuat intdan longtidak berguna karena Anda tidak tahu harus berhenti di mana dengan desimal.
  • BigDecimalakan memberi Anda presisi sewenang-wenang tetapi akan menjadi sangat lambat, kecuali jika Anda menjepit presisi pada suatu saat. Apa aturan pembulatannya? Bagaimana Anda memilih tempat untuk berhenti? Apakah layak memiliki bit presisi lebih banyak daripada double? Saya percaya tidak.

Alasan fixed point aritmatika digunakan dalam aplikasi keuangan adalah karena mereka bersifat deterministik. Aturan pembulatan didefinisikan dengan sempurna, kadang-kadang oleh hukum, dan harus diterapkan secara ketat, tetapi pembulatan masih terjadi di beberapa titik. Argumen apa pun yang mendukung tipe tertentu berdasarkan presisi cenderung palsu. Semua tipe memiliki masalah presisi dengan jenis perhitungan yang akan Anda lakukan.

Contoh-contoh praktis

Saya melihat beberapa komentar mengklaim hal-hal tentang pembulatan atau ketepatan yang saya tidak setuju. Berikut adalah beberapa contoh tambahan untuk menggambarkan apa yang saya maksud.

Menyimpan : jika unit dasar Anda adalah cent, Anda mungkin ingin membulatkan ke cent terdekat saat menyimpan nilai:

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

Anda tidak akan mendapatkan masalah pembulatan saat mengadopsi metode ini yang tidak akan Anda miliki dengan tipe integer.

Mengambil : semua perhitungan dapat dilakukan secara langsung pada nilai ganda, tanpa konversi:

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

Perhatikan bahwa kode di atas tidak berfungsi jika Anda ganti doubledengan int64_t: akan ada konversi implisit ke double, kemudian pemotongan ke int64_t, dengan kemungkinan hilangnya informasi.data.GetValue ()

Membandingkan : perbandingan adalah satu hal yang harus dilakukan dengan tipe floating-point. Saya sarankan menggunakan metode perbandingan seperti ini:

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

Membulatkan keadilan

Misalkan Anda memiliki $ 9,99 dalam akun dengan bunga 4%. Berapa banyak yang pemain dapat hasilkan? Dengan pembulatan integer Anda mendapatkan $ 0,03; dengan pembulatan floating-point Anda mendapatkan $ 0,04. Saya percaya yang terakhir ini lebih adil.


4
+1. Satu-satunya klarifikasi yang ingin saya tambahkan, adalah seperti halnya aplikasi keuangan sesuai dengan persyaratan yang telah ditentukan sebelumnya, demikian pula algoritma pembulatannya. Jika gim ini adalah kasino, gim ini sesuai dengan standar yang sama dan gandakan bukan opsi.
Ivaylo Slavov

2
Anda masih harus memikirkan tentang aturan pembulatan untuk memformat UI. Karena selalu ada sebagian kecil dari pemain yang akan mencoba memperlakukan permainan sebagai spreadsheet jika Anda tidak ingin berurusan dengan orang-orang yang melompat-lompat menjerit ketika mereka menemukan backend Anda tidak menggunakan ketepatan yang sama seperti UI Anda sehingga menghasilkan 'salah' hasil yang ditampilkan pilihan terbaik Anda untuk tetap diam adalah dengan menggunakan representasi internal dan eksternal yang sama yang berarti menggunakan format titik tetap. Kecuali jika kinerja menjadi masalah, BigDecimal adalah pilihan terbaik untuk melakukan ini.
Dan Neely

10
Saya tidak setuju dengan jawaban ini. Masalah pembulatan memang muncul, dan jika mereka turun, dan jika Anda tidak menggunakan pembulatan tambahan, $ 1,00 tiba-tiba bisa menjadi $ 0,99. Tetapi yang paling penting, desimal presisi acak yang lambat (hampir) sama sekali tidak relevan. Kami hampir di 2013, dan kecuali Anda melakukan faktorisasi besar, memicu hal-hal atau logaritma lebih dari beberapa juta angka dengan ribuan digit, Anda bahkan tidak akan pernah melihat kinerja yang buruk. Bagaimanapun, sederhana selalu yang terbaik, jadi rekomendasi saya adalah untuk menyimpan semua angka sebagai sen. Dengan begitu mereka semua int_64ts.
Panda Pajama

8
@ Sam, terakhir kali saya memeriksa rekening bank saya, saldo saya tidak berakhir dengan 0,0000000000000001. Sistem mata uang riil harus bekerja dengan unit yang tidak dapat dibagi, dan itu diwakili dengan benar dengan bilangan bulat. Jika Anda harus melakukan pembagian mata uang dengan benar (yang sebenarnya sama sekali tidak umum di dunia keuangan nyata), Anda harus melakukannya sehingga uang tidak hilang. Misalnya 10/3 = 3+3+4atau 10/3 = 3+3+3 (+1). Untuk semua operasi lainnya, bilangan bulat bekerja dengan sempurna, tidak seperti floating point yang bisa mendapatkan masalah pembulatan dalam operasi apa pun.
Panda Pajama

2
@SamHocevar 999 * 4/100. Apabila tidak ditentukan oleh peraturan, anggap semua pembulatan akan dilakukan demi kepentingan bank.
Dan Neely

21

Jenis titik apung di Jawa ( float, double) bukan representasi yang baik untuk mata uang karena satu alasan utama - ada kesalahan mesin dalam pembulatan. Bahkan jika perhitungan sederhana mengembalikan seluruh nomor - seperti 12.0/2(6.0), floating point mungkin salah bulat itu (karena tho representasi spesifik jenis dalam memori) sebagai 6.0000000000001atau 5.999999999999998atau mirip. Ini adalah hasil dari pembulatan mesin spesifik yang terjadi pada prosesor dan unik untuk komputer yang menghitungnya. Biasanya, jarang ada masalah untuk beroperasi dengan nilai-nilai ini, karena kesalahannya cukup lalai, tetapi sulit untuk menampilkannya kepada pengguna.

Solusi yang mungkin untuk ini adalah dengan menggunakan implementasi kustom tipe data floating point, seperti BigDecimal. Ini mendukung mekanisme perhitungan yang lebih baik yang setidaknya mengisolasi kesalahan pembulatan bukan untuk mesin spesifik, tetapi lebih lambat dalam hal kinerja.

Jika Anda membutuhkan produktivitas tinggi, Anda sebaiknya tetap menggunakan tipe yang sederhana. Jika Anda beroperasi dengan data keuangan penting , dan setiap sen penting (seperti aplikasi Forex, atau permainan kasino) maka saya sarankan Anda untuk menggunakan Longatau long. Longakan memungkinkan Anda untuk menangani jumlah besar dan presisi yang baik. Anggap saja Anda membutuhkan, katakanlah, 4 digit setelah titik desimal, yang Anda butuhkan adalah mengalikan jumlahnya dengan 10.000. Memiliki pengalaman dalam mengembangkan game kasino online, saya Longsering terlihat sering mewakili uang dalam sen . Dalam aplikasi Forex, ketepatan lebih penting, sehingga Anda akan membutuhkan pengali yang lebih besar - tetap saja, bilangan bulat bebas dari masalah pembulatan mesin (tentu saja pembulatan manual seperti pada 3/2 yang harus Anda tangani sendiri).

Pilihan yang dapat diterima adalah menggunakan tipe floating point standar - Floatdan Double, jika kinerja lebih penting daripada akurasi hingga ratusan persen. Kemudian, pada logika tampilan Anda, yang Anda butuhkan adalah menggunakan pemformatan yang telah ditentukan , sehingga keburukan dari pembulatan mesin potensial tidak sampai ke pengguna.


4
+1 Detail: "Anggap saja Anda perlu, katakanlah, 4 digit setelah titik desimal, yang Anda butuhkan adalah mengalikan jumlahnya dengan 1000." -> Ini disebut titik tetap.
Laurent Couvidou

1
@ Sam, angka-angka diberikan untuk pasak contoh. Meski begitu, saya pribadi melihat hasil aneh dengan angka sederhana seperti itu, tetapi ini bukan skenario yang sering. Ketika poin mengambang datang untuk bermain, ini mungkin lebih mungkin terjadi, tetapi lebih mungkin untuk menemukan
Ivaylo Slavov

2
@Ivaylo Slavov, saya setuju dengan Anda. Dalam jawaban saya, saya hanya membuat pendapat saya. Saya suka berdiskusi dan memiliki kemauan untuk mengambil hal yang benar. Juga terima kasih atas pendapat Anda. :)
Md Mahbubur Rahman

1
@ SamHocevar: Alasan itu tidak bekerja dalam semua kasus. Lihat: ideone.com/nI2ZOK
Samaursa

1
@ SamHocevar: Itu juga tidak dijamin. Angka dalam kisaran yang masih bilangan mulai mengumpulkan kesalahan pada divisi pertama: ideone.com/AKbR7i
Samaursa

17

Untuk game skala kecil dan di mana kecepatan proses, memori adalah masalah penting (karena presisi atau bekerja dengan co-prosesor matematika dapat membuat sangat lambat), ada dua kali lipat sudah cukup.

Tetapi untuk game skala besar (misalnya, game sosial) dan di mana kecepatan proses, memori tidak terbatas, ada BigDecimal lebih baik. Karena di sini,

  • int atau panjang untuk perhitungan moneter.
  • pelampung dan ganda tidak dapat secara akurat mewakili bilangan real 10 basis paling.

Sumber:

Dari https://stackoverflow.com/questions/3730019/why-not-use-double-or-float-to-represent-currency

Karena float dan dobel tidak dapat secara akurat mewakili bilangan real 10 basis paling.

Ini adalah bagaimana angka floating-point IEEE-754 bekerja: ia mendedikasikan sedikit untuk tanda, beberapa bit untuk menyimpan eksponen, dan sisanya untuk fraksi yang sebenarnya. Ini mengarah ke angka yang diwakili dalam bentuk yang mirip dengan 1,45 * 10 ^ 4; kecuali bahwa alih-alih basis menjadi 10, itu dua.

Semua bilangan desimal nyata dapat dilihat, pada kenyataannya, sebagai pecahan tepat dari kekuatan sepuluh. Misalnya, 10,45 benar-benar 1045/10 ^ 2. Dan seperti beberapa pecahan yang tidak dapat direpresentasikan persis sebagai pecahan dari kekuatan sepuluh (1/3 terlintas dalam pikiran), beberapa dari mereka tidak dapat direpresentasikan persis sebagai pecahan dari kekuatan dua, juga. Sebagai contoh sederhana, Anda tidak bisa menyimpan 0,1 di dalam variabel floating-point. Anda akan mendapatkan nilai representatif terdekat, yaitu sekitar 0,0999999999999999996, dan perangkat lunak akan membulatkannya menjadi 0,1 saat menampilkannya.

Namun, saat Anda melakukan lebih banyak penambahan, pengurangan, perkalian, dan pembagian pada angka yang tidak tepat, Anda akan kehilangan lebih banyak dan lebih presisi ketika kesalahan kecil bertambah. Ini membuat float dan double tidak memadai untuk berurusan dengan uang, di mana akurasi yang sempurna diperlukan.

Dari Bloch, J., Java Efektif, edisi ke-2, Item 48:

The float and double types are particularly ill-suited for 

perhitungan moneter karena tidak mungkin untuk mewakili 0,1 (atau kekuatan negatif sepuluh lainnya) sebagai float atau double persis.

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 atau panjang untuk perhitungan moneter.

Lihat juga


Saya hanya tidak setuju dengan bagian yang lama cocok untuk perhitungan kecil. Dalam pengalaman kehidupan nyata saya, telah terbukti cukup untuk menangani presisi yang baik dan sejumlah besar uang Ya, itu mungkin sedikit rumit untuk digunakan tetapi mengalahkan BigDecimal dalam dua poin penting - 1) lebih cepat (BigDecimal menggunakan pembulatan perangkat lunak, yang jauh lebih lambat dibandingkan pembulatan CPU bawaan yang digunakan dalam float / double) dan 2) BigDecimal lebih sulit bertahan dalam basis data tanpa kehilangan presisi - tidak semua database mendukung tipe 'khusus' tersebut. Long dikenal luas dan didukung secara luas di semua basis data utama.
Ivaylo Slavov

@Ivaylo Slavov, Maaf atas kesalahan saya. Saya telah memperbarui jawaban saya.
Md Mahbubur Rahman

Tidak ada permintaan maaf yang diperlukan untuk memberikan pendekatan berbeda untuk masalah yang sama :)
Ivaylo Slavov

2
@Ivaylo Slavov, saya setuju dengan Anda. Dalam jawaban saya, saya hanya membuat pendapat saya. Saya suka berdiskusi dan memiliki kemauan untuk mengambil hal yang benar. Juga terima kasih atas pendapat Anda. :)
Md Mahbubur Rahman

tujuan situs ini adalah untuk mengklarifikasi masalah dan membantu OP membuat keputusan yang tepat, tergantung pada skenario spesifik. Yang bisa kami lakukan adalah membantu mempercepat prosesnya :)
Ivaylo Slavov

13

Anda ingin menyimpan mata uang Anda longdan menghitung mata uang Anda double, setidaknya sebagai cadangan. Anda ingin semua transaksi terjadi sebagai long.

Alasan Anda ingin menyimpan mata uang Anda longadalah karena Anda tidak ingin kehilangan mata uang apa pun.

Misalkan Anda menggunakan double, dan Anda tidak punya uang. Seseorang memberi Anda tiga sen, lalu membawanya kembali.

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

Yah, itu tidak terlalu keren. Mungkin seseorang dengan $ 10 ingin memberikan kekayaannya dengan terlebih dahulu memberi Anda tiga sen, dan kemudian memberikan $ 9,70 kepada orang lain.

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

Dan kemudian Anda memberi mereka uang receh kembali:

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

Ini baru saja rusak.

Sekarang, mari kita gunakan yang panjang, dan kami akan melacak sepersepuluh sen (jadi 1 = $ 0,001). Mari kita beri setiap orang di planet ini satu miliar, seratus dua belas juta, tujuh puluh lima ribu, seratus empat puluh tiga dolar:

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

Um, tunggu, kita bisa memberi semua orang lebih dari satu miliar dolar, dan hanya menghabiskan sedikit lebih dari dua? Overflow adalah bencana di sini.

Jadi, setiap kali Anda menghitung jumlah uang yang akan ditransfer, gunakan doubledan Math.rounditu untuk mendapatkan long. Kemudian perbaiki saldo (tambahkan dan kurangi kedua akun) menggunakan long.

Ekonomi Anda tidak akan bocor, dan akan meningkat hingga empat triliun dolar.

Ada masalah yang lebih rumit - misalnya, apa yang Anda lakukan jika Anda melakukan dua puluh pembayaran? * - tetapi ini harus Anda mulai.

* Anda menghitung apa satu pembayaran, bulat ke long; kemudian kalikan dengan 20.0dan periksa apakah itu dalam jangkauan; jika demikian, Anda melipatgandakan pembayaran dengan 20Luntuk mendapatkan jumlah yang dikurangkan dari saldo Anda. Secara umum, semua transaksi harus ditangani long, jadi Anda benar-benar perlu meringkas semua transaksi individu; Anda dapat mengalikannya sebagai pintasan, tetapi Anda harus memastikan bahwa Anda tidak menambahkan kesalahan pembulatan dan bahwa Anda tidak meluap, yang berarti Anda perlu memeriksa doublesebelum melakukan perhitungan nyata dengan long.


8

Saya akan mengatakan bahwa nilai apa pun yang dapat ditampilkan kepada pengguna hampir selalu berupa bilangan bulat. Uang hanyalah contoh paling menonjol dari ini. Menangani 225 kerusakan empat kali pada monster dengan 900 HP dan menemukan bahwa itu masih memiliki 1 HP tersisa akan mengurangi pengalaman sama seperti menemukan bahwa Anda adalah fraksi tak terlihat dari satu sen pendek kekurangan sesuatu yang memberikan sesuatu.

Di sisi yang lebih teknis saya pikir perlu dicatat bahwa seseorang tidak harus kembali ke pelampung untuk melakukan hal-hal canggih seperti minat. Selama Anda memiliki cukup ruang kepala di bilangan bulat yang Anda pilih, perkalian dan sebuah divisi akan bertahan untuk perkalian dengan angka desimal, misalnya untuk menambah 4%, dibulatkan ke bawah:

number=(number*104)/100

Untuk menambah 4%, dibulatkan oleh konvensi standar:

number=(number*104+50)/100

Tidak ada titik float yang tidak akurat di sini, pembulatan selalu terbelah tepat pada .5sasaran.

Edit, pertanyaan sebenarnya:

Melihat bagaimana perdebatan telah pergi aku mulai berpikir bahwa menguraikan apa pertanyaannya adalah semua tentang mungkin lebih berguna daripada sederhana int/ floatjawaban. Inti dari pertanyaan ini bukan tentang tipe data, ini tentang mengendalikan detail suatu program.

Menggunakan integer untuk mewakili nilai non-integer memaksa programmer untuk berurusan dengan detail implementasi. "Apa presisi yang digunakan?" dan "Cara apa untuk berputar?" adalah pertanyaan yang harus dijawab secara eksplisit.

Melayang di sisi lain tidak memaksa programmer untuk khawatir, itu sudah cukup banyak melakukan apa yang diharapkan. Tetapi karena pelampung bukanlah presisi yang tidak terbatas, beberapa pembulatan akan terjadi, dan pembulatan itu sangat tidak terduga.

Apa yang terjadi dalam sekali pakai mengapung dan ingin mengendalikan pembulatan? Ternyata hampir mustahil. Satu-satunya cara untuk membuat float benar-benar dapat diprediksi adalah dengan hanya menggunakan nilai-nilai yang dapat direpresentasikan secara keseluruhan 2^n. Tapi konstruksi itu membuat pelampung cukup sulit untuk digunakan.

Jadi jawaban untuk pertanyaan sederhana adalah: Jika Anda ingin mengambil kendali, gunakan bilangan bulat, jika tidak, gunakan float.

Tetapi pertanyaan yang sedang diperdebatkan hanyalah bentuk lain dari pertanyaan: Apakah Anda ingin mengambil kendali?


5

Bahkan jika itu "hanya permainan", saya akan menggunakan Pola Uang dari Martin Fowler, didukung oleh lama.

Mengapa?

Lokalisasi (L10n): Menggunakan pola itu Anda dapat dengan mudah melokalkan mata uang game Anda. Pikirkan tentang game taipan lama seperti "Transport Tycoon". Mereka dengan mudah memungkinkan pemain untuk mengubah mata uang dalam game (yaitu Dari Pound Inggris ke Dolar AS) untuk memenuhi mata uang dunia nyata.

Dan

Tipe data yang panjang adalah integer komplemen dua ditandatangani bertanda 64-bit. Ini memiliki nilai minimum -9.223.372.036.854.775.808 dan nilai maksimum 9.223.372.036.854.775.807 (inklusif) ( Tutorial Java )

Itu berarti Anda dapat menyimpan 9000 kali Pasokan Uang M2 AS saat ini (~ 10.000 Miliar Dolar). Memberi Anda cukup ruang untuk menggunakan mata uang dunia lainnya, mungkin, bahkan mereka yang pernah / memiliki hiperinflasi (Jika penasaran, lihat inflasi Jerman pasca Perang Dunia I , di mana 1 pon roti adalah 3.000.000.000 mark)

Panjang mudah untuk bertahan, sangat cepat dan harus memberi Anda ruang yang cukup untuk melakukan semua perhitungan bunga hanya menggunakan integer arithmetics, jawaban eBusiness memberikan penjelasan tentang cara melakukannya.


2

Berapa banyak pekerjaan yang ingin Anda lakukan dalam hal ini? Seberapa penting akurasi? Apakah Anda peduli melacak kesalahan fraksional yang terjadi dengan pembulatan dan ketidaktepatan mewakili angka desimal dalam sistem biner?

Pada akhirnya saya cenderung menghabiskan sedikit lebih banyak waktu pengkodean dan mengimplementasikan unit test untuk "kasus sudut" dan kasus bermasalah yang diketahui - jadi saya akan berpikir dalam hal BigInteger yang dimodifikasi yang mencakup jumlah besar secara sewenang-wenang dan mempertahankan bit fraksional dengan BigDecimal atau bagian BigRational (dua BigIntegers, satu untuk penyebut dan yang lain untuk pembilang) - dan termasuk kode untuk menjaga bagian pecahan menjadi fraksi yang sebenarnya dengan (mungkin hanya secara berkala) menambahkan bagian non-fraksional ke BigInteger utama. Lalu saya akan secara internal melacak segala sesuatu dalam sen hanya untuk menjaga bagian-bagian pecahan dari perhitungan GUI.

Mungkin cara kompleks untuk gim (sederhana) - tetapi bagus untuk perpustakaan yang diterbitkan sebagai sumber terbuka! Hanya perlu mencari cara untuk menjaga kinerja yang baik ketika berhadapan dengan bit fraksional ...


1

Tentu tidak melayang. Dengan hanya 7 digit, Anda hanya memiliki akurasi seperti:

12,345,67 123,456.7x

Jadi Anda tahu, sudah dengan 10 ^ 5 dolar, Anda kehilangan jejak uang. ganda dapat digunakan untuk tujuan game, bukan dalam kehidupan nyata karena masalah akurasi.

Tapi panjang (dan maksud saya ini 64 bit, atau panjang dalam C ++) tidak cukup jika Anda akan melacak transaksi dan menjumlahkannya. Itu cukup untuk mempertahankan kepemilikan bersih perusahaan mana pun, tetapi semua transaksi selama setahun bisa meluap. Itu tergantung pada seberapa besar "dunia" finansial Anda dalam permainan.


0

Solusi lain yang akan saya tambahkan di sini adalah membuat kelas uang. Kelasnya akan seperti (bahkan bisa menjadi struct).

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;
}

Ini akan memungkinkan Anda untuk mewakili sen dalam hal ini sebagai bilangan bulat dan seluruh dolar sebagai bilangan bulat. Karena Anda memiliki panji terpisah untuk menjadi negatif, Anda dapat menggunakan bilangan bulat tidak bertanda untuk nilai-nilai Anda yang menggandakan jumlah yang mungkin (Anda juga bisa menulis kelas angka yang menerapkan ide ini ke angka untuk mendapatkan angka yang BENAR-BENAR besar). Yang perlu Anda lakukan adalah membebani operator matematika dan Anda bisa menggunakan ini seperti tipe data lama. Membutuhkan lebih banyak memori, tetapi benar-benar memperluas batas nilai.

Ini lebih lanjut dapat diperluas untuk mencakup hal-hal seperti jumlah unit parsial per seluruh unit sehingga Anda dapat memiliki mata uang yang membagi sesuatu selain 100 sub unit, sen dalam hal ini, per dolar. Misalnya, Anda dapat membuat 125 floopies untuk membuat satu flooper.

Sunting:

Saya akan memperluas gagasan bahwa Anda juga dapat melihat daftar jenis, yang dapat diakses oleh kelas uang yang akan memberikan nilai tukar untuk mata uangnya versus semua mata uang lainnya. Anda dapat membuat ini menjadi fungsi operator yang berlebihan. Karena itu, jika Anda secara otomatis mencoba menambahkan 4 USD ke 4 poundsterling Inggris, itu akan secara otomatis memberi Anda 6,6 pound (pada saat penulisan).



-1

Gunakan kelas itu cara terbaik. Anda dapat menyembunyikan implementasi uang Anda, Anda dapat mengganti dua kali / panjang apa pun yang Anda inginkan setiap saat.

Contoh

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
    }
}

Dalam penggunaan kode Anda cukup rajin giat itu saya pikir dan Anda dapat menyimpan metode yang lebih berguna.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.