Newsgroup: it.comp.www.php
Titolo: errore arrotondamento di bcdiv con BC MATH

Salve a tutti la comunity.
 
Ho un problema da sottoporre alla Vs. attenzione in merito ad un risultato che ottengo facendo eseguire al server una semplice divisione utilizzando la funzione bcdiv della libreria BCMATH. 
 
In pratica, non devo far altro che far calcolare l'imposta IVA da una base imponibile.
 
Parte delle variabili in gioco, che ovviamente sono delle stringhe, vengono precedentemente imputate dall'utente tramite un form ...e sono con 2 sole cifre decimali.
 
Il problema che mi si presenta è legato ad un arrotondamento che non sembra essere corretto!!!
 
Inizialmente avevo scritto tutte le formule con bcscale(2) e utilizzato, per ciascuna funzione matematica, il parametro (2) per la precisione arbitraria.
 
Quando mi sono accorto del problema (ossia un mancato arrotondamendo di un risultato), ho alzato il bcscale da 2 a 5 e poi ancora, ho alzato il parametro della precisione arbitraria da 2 a 5. Ma niente!!! Ho sempre un valore errato.
 
Più esattamente, la situazione attuale è la seguente:
$Totale = 6468.00;
$Cassa = 258.72;
bcscale(5);
$Imponibile = bcadd($Totale, $Cassa, 5); //6726.72000
$tmpValue = bcmul($Imponibile, $AliquotaIVA, 5); //147987.84000
$IVA = bcdiv($tmpValue, "100.00", 5); // 1479.87840
 
Quindi, il risultato della variabile $IVA che ottengo è pari a 1479.87840
 
Il problema è che dovrei rappresentare questo valore con due sole cifre decimali e quindi ottenere il risultato correttamente arrotondato pari a (1479.88).
 
Ho provato, forse stupidamente, ad eseguire un ultima operazione fittizzia con bcscale(2)
 
$IVA = bcadd($IVA, "0.00", 2);
 
con la speranza di vedere correttamente arrotondato il valore di $IVA = 1479.88 ...ed invece ottengo $IVA = 1479.87
 
Come procedere ?! Chi può illuminarmi ?
 
 
Grazie a tutti per l'attenzione.
 
 
 
 
 
 
 


 
-- 
Andrea
 

 arbitraria.
 
bcscale non definisce l'arrotondamento, ma il troncamento.
 
Per arrotondare puoi provare con round(), se il risultato è entro i 
limiti del tuo sistema (32 o 64bit), oppure calcolartelo a mano con le 
funzioni bcmath (moltiplicamdo per 100, dimenticando i decimali e ri-
dividendo per 100)
 
In caso di valuta "normale" (quindi non operazioni bancarie o finanziarie 
ingenti) io preferisco moltiplicare tutto per 100 e calcolare con 
aritmetica intera.
 
Su un sistema a 64bit sei tranquillo fino a qualche centinaio di miliardi, 
mi pare.
 
Su un 32bit solo fino a 40.000.000 circa. :D
 
Bye.


Ringrazio tutti per la premura e l'attenzione.
Avevo una grande urgenza di risolvere il problema e nell'attesa che l'anima pia del momento trovasse tempo prezioso per dedicarsi a questo mio ostacolo, ho provato (con successo) ad inventarmi una (forse macchinosa) soluzione.
 
E cioè, ...ho creato questa piccola funzione:
 
function arrotondamendo($str)
{
	$str = (float)$str;
	$str = round($str, 2);
	$str = sprintf("%01.2f", $str);
return $str;
 
Forse ci sarà del codice inutile; quindi ottimizzabile, ...ma per adesso il risultato è ciò che conta di più.
 
Mi confortano le risposte ricevute che mi confermano le soluzioni individuabili.
 
Grazie ancora ...e buon lavoro.
 
Maurizio

 return $str;
 
"Welcome to Tool Command Language."
 
 
-- 
Andrea
 

 return $str;
 
Così però perdi la precisione di bcmath, ricadendo nella floating-point. 
Come ho detto, dipende da cosa ti serve e dalla grandezza dei numeri che 
gestisci.
 
Comunque ti bastava
 
print number_format($str, 2);
 
Eventualmente 
 
print number_format($str, 2, '.'. '');
 
se non vuoi il separatore delle migliaia.
 
PHP converte implicitamente il tipo a float prima del number_format, che 
poi arrotonda.
 
Bye.
 


Ma la funzione la utilizzo così come nell'esempio che segue:
 
$ImportoRitenuta = arrotondamento(bcdiv(bcmul($PrezzoTotale, $AliquotaRitenuta, 5), "100.00", 5));
 
Perdo lo stesso la precisione !?