Di recente abbiamo implementato un sistema che deve gestire i valori in più valute e convertirle tra loro, e abbiamo capito alcune cose nel modo più duro.
NON UTILIZZARE MAI NUMERI DI PUNTI GALLEGGIANTI PER SOLDI
L'aritmetica in virgola mobile introduce inesattezze che potrebbero non essere notate fino a quando non hanno rovinato qualcosa. Tutti i valori devono essere archiviati come numeri interi o decimali fissi e, se si sceglie di utilizzare un tipo decimale fisso, assicurarsi di comprendere esattamente cosa fa quel tipo sotto il cofano (ovvero, utilizza internamente un numero intero o virgola mobile genere).
Quando è necessario eseguire calcoli o conversioni:
- Converti i valori in virgola mobile
- Calcola nuovo valore
- Arrotondare il numero e riconvertirlo in un numero intero
Quando converti un numero in virgola mobile in un numero intero nel passaggio 3, non limitarti a lanciarlo, ma usa una funzione matematica per arrotondarlo per primo. Questo di solito lo sarà round
, anche se in casi speciali potrebbe essere floor
o ceil
. Conosci la differenza e scegli attentamente.
Memorizza il tipo di un numero accanto al valore
Questo potrebbe non essere così importante per te se stai gestendo solo una valuta, ma è stato importante per noi nella gestione di più valute. Abbiamo usato il codice di 3 caratteri per una valuta, come USD, GBP, JPY, EUR, ecc.
A seconda della situazione, può anche essere utile memorizzare:
- Se il numero è prima o dopo le imposte (e quale era l'aliquota fiscale)
- Se il numero è il risultato di una conversione (e da cosa è stato convertito)
Conosci i limiti di precisione dei numeri con cui hai a che fare
Per valori reali, vuoi essere preciso come la più piccola unità della valuta. Ciò significa che non hai valori inferiori a un centesimo, un penny, uno yen, un fen, ecc. Non memorizzare valori con una precisione superiore a quella senza motivo.
Internamente, puoi scegliere di gestire valori inferiori, nel qual caso si tratta di un diverso tipo di valore valutario . Assicurati che il tuo codice sappia quale è quale e che non li confonda. Evita di usare valori in virgola mobile anche qui.
Sommando tutte quelle regole insieme, abbiamo deciso le seguenti regole. Nel codice in esecuzione, le valute vengono archiviate utilizzando un numero intero per l'unità più piccola.
class Currency {
String code; // eg "USD"
int value; // eg 2500
boolean converted;
}
class Price {
Currency grossValue;
Currency netValue;
Tax taxRate;
}
Nel database, i valori sono archiviati come stringa nel seguente formato:
USD:2500
Ciò memorizza il valore di $ 25,00. Siamo stati in grado di farlo solo perché il codice che si occupa delle valute non ha bisogno di essere all'interno del livello del database stesso, quindi tutti i valori possono essere prima convertiti in memoria. Altre situazioni si presteranno senza dubbio ad altre soluzioni.
E nel caso non lo avessi chiarito prima, non usare float!