2010-09-29 9 views
27

Ho bisogno di aggiungere, moltiplicare e confrontare i valori di valuta in PHP e ho bisogno di essere sicuro che sia esatto in un solo centesimo.Le migliori pratiche per lavorare con i valori di valuta in PHP?

Un modo è quello di memorizzare tutto in virgola mobile, utilizzare round prima e dopo ogni operazione e mente epsilon della macchina quando si confronta per l'uguaglianza. Abbastanza ingombrante.

Un altro modo è di memorizzare l'intero importo come centesimi nei tipi di dati interi, oltre a ricordare di convertire avanti e indietro ogni volta che lavoro con il database (mysql, dove utilizzo il tipo di dati decimali). Inelegante, e molti errori di errore, imho.

Un altro modo è inventare il mio "tipo di dati", memorizzare tutti i valori nelle stringhe ("34.12") e creare le mie funzioni di sostituzione matematica. Queste funzioni convertono il valore in interi internamente, eseguono il calcolo e restituiscono il risultato di nuovo a stringhe. Sorprendentemente complicato, imho.

La mia domanda: qual è la migliore pratica per lavorare con i valori di valuta in PHP? Grazie!

risposta

5

Lasciatemi rispondere io stesso. La migliore pratica sarebbe quella di creare una classe "quantità di denaro". Questa classe memorizza internamente l'importo in centesimi in interi e offre getters, setter, funzioni matematiche come add, sottrarre e confrontare. Molto più pulito

+3

Questo non è, molto semplicemente, le migliori pratiche e molto male consigli. Per favore, con tutti i mezzi, incapsulare le funzioni che funzionano con le funzioni matematiche di precisione arbitrarie, ma per favore non seguire i suggerimenti sopra riportati. La migliore risposta è Andrew Dunn. –

3

Aggiornamento 2016:

Un paio di anni più tardi, e si spera un po 'più saggio;)
Dal momento che questa risposta riceve ancora l'up-occasionale e verso il basso voto ho sentito la necessità di rivedere la mia risposta. Non consiglio assolutamente di memorizzare 'soldi' come numeri interi. L'unica vera risposta è Andrew Dunn: usa il tipo DECIMAL di Mysql e incapsula le funzioni bc_ * di php in una classe di valuta.


terrò la mia risposta obsoleto per completezza amor

Si dovrebbe sempre lavorare con numeri interi. Memorizza i valori come valori in nel database, utilizza i dati per eseguire calcoli e quando, e solo quando, vuoi stamparlo, convertilo in un formato leggibile.

In questo modo si completeley aggirare galleggiante problemi puntiformi che, in generale, è un grosso problema quando si lavora con il denaro;)

Edit: Un aspetto degno di nota: è necessario pensare a precisione prima di iniziare a lavorare per di qua. Come altri hanno sottolineato, è possibile che sia necessario utilizzare con valori inferiori a un centesimo, quindi è necessario eseguire la moltiplicazione/divisione di conseguenza. (Cioè valuta * 1000 per una precisione .001)

+2

MySQL e altri hanno il formato DECIMAL/NUMERIC che è progettato specificamente per aggirare i problemi in virgola mobile e fornire risultati esatti. –

+3

Ho assunto l'ironia, quindi non ho votato. Per favore conferma che avevo ragione :) – thomasmalt

+1

@Tatu Ulmanen: Certo, lo fa Mysql. Ma se poi vai avanti e fai qualcosa come test di uguaglianza in php, potresti ottenere risultati inaspettati. –

22

partire da MySQL v5.0.3, MySQLs DECIMAL tipo di dati memorizza un numero decimale esatto, cioè non una rappresentazione inesatta virgola mobile.

Per manipolare correttamente i numeri di precisione in PHP, utilizzare arbitrary precision math functions. Internamente questa libreria manipola le stringhe di testo.

La valuta deve essere memorizzata come numero decimale, è possibile ottenere unità di denaro inferiori a centesimi. Dovresti arrotondare i valori solo quando visualizzi le figure, non durante la manipolazione o la memorizzazione.

+1

Mi dispiace ma non ti capisco. Non esiste alcun tipo di dati decimali in php. Se intendevi float: non puoi testare in modo attendibile l'uguaglianza usandoli. – CruftyCraft

+10

PHP ha una serie di funzioni progettate specificamente per la manipolazione e il confronto di numeri di precisione: http://www.php.net/manual/en/ref.bc.php –

0

Mantieni i valori come centesimi e utilizza numeri interi.Scrivi classi o funzioni di supporto per incapsulare la visualizzazione nell'interfaccia utente e gestire i valori nelle query del database. Se usi float, c'è troppo rischio di perdere un centesimo da qualche parte.

Problemi correlati