Kami baru-baru ini mengimplementasikan sistem yang perlu menangani nilai dalam berbagai mata uang dan mengkonversi di antara mereka, dan menemukan beberapa hal dengan cara yang sulit.
JANGAN PERNAH MENGGUNAKAN NOMOR TITIK FLOATING UNTUK UANG
Aritmatika titik mengambang memperkenalkan ketidakakuratan yang mungkin tidak diperhatikan sampai mereka mengacaukan sesuatu. Semua nilai harus disimpan sebagai bilangan bulat atau tipe desimal tetap, dan jika Anda memilih untuk menggunakan tipe desimal tetap maka pastikan Anda memahami dengan tepat apa yang dilakukan tipe di bawah tenda (yaitu, apakah secara internal menggunakan bilangan bulat atau titik mengambang Tipe).
Ketika Anda perlu melakukan perhitungan atau konversi:
- Konversi nilai menjadi floating point
- Hitung nilai baru
- Membulatkan angka dan mengubahnya kembali menjadi bilangan bulat
Saat mengonversi angka floating point kembali ke integer pada langkah 3, jangan hanya melemparkannya - gunakan fungsi matematika untuk membulatkannya terlebih dahulu. Ini biasanya round
, meskipun dalam kasus khusus bisa floor
atau ceil
. Ketahui perbedaannya dan pilih dengan cermat.
Simpan jenis angka di samping nilainya
Ini mungkin tidak sepenting bagi Anda jika Anda hanya menangani satu mata uang, tetapi penting bagi kami dalam menangani banyak mata uang. Kami menggunakan kode 3 karakter untuk mata uang, seperti USD, GBP, JPY, EUR, dll.
Bergantung pada situasinya, mungkin berguna juga untuk menyimpan:
- Apakah nomor tersebut sebelum atau sesudah pajak (dan berapa tarif pajaknya)
- Apakah nomor tersebut merupakan hasil konversi (dan dari mana itu dikonversi)
Ketahui batas akurasi angka yang Anda hadapi
Untuk nilai nyata, Anda ingin setepat unit terkecil dari mata uang. Ini berarti Anda tidak memiliki nilai lebih kecil dari sen, sen, yen, fen, dll. Jangan menyimpan nilai dengan akurasi lebih tinggi dari itu tanpa alasan.
Secara internal, Anda dapat memilih untuk berurusan dengan nilai yang lebih kecil, dalam hal ini jenis nilai mata uang yang berbeda . Pastikan kode Anda tahu yang mana dan tidak mencampuradukkannya. Hindari menggunakan nilai floating point bahkan di sini.
Menambahkan semua aturan itu bersama-sama, kami memutuskan aturan berikut. Dalam menjalankan kode, mata uang disimpan menggunakan integer untuk unit terkecil.
class Currency {
String code; // eg "USD"
int value; // eg 2500
boolean converted;
}
class Price {
Currency grossValue;
Currency netValue;
Tax taxRate;
}
Dalam database, nilai-nilai disimpan sebagai string dalam format berikut:
USD:2500
Itu menyimpan nilai $ 25,00. Kami dapat melakukan itu hanya karena kode yang berhubungan dengan mata uang tidak perlu berada di dalam lapisan basis data itu sendiri, sehingga semua nilai dapat dikonversi menjadi memori terlebih dahulu. Situasi lain tidak diragukan lagi akan memberikan solusi lain.
Dan jika saya tidak menjelaskan sebelumnya, jangan gunakan float!