← Back to team overview

openerp-expert-accounting team mailing list archive

Re: wrong currency rounding

 

Am Donnerstag 10 November 2011, 08:15:06 schrieb Lorenzo Battistini:
> I'm forwarding this mail to list as it is relevant and seems it was
> not delivered
may be we should check / fix / use (trunk)
base/res/res_currency.py

    def round(self, cr, uid, currency, amount):
        if currency.rounding == 0:
            return 0.0
        else:
            # /!\ First member below must be rounded to full unit!
            # Do not pass a rounding digits value to round()
            return round(amount / currency.rounding) * currency.rounding

    def is_zero(self, cr, uid, currency, amount):
        return abs(self.round(cr, uid, currency, amount)) < currency.rounding


> 
> ---------- Forwarded message ----------
> From: Olivier Dony <odo@xxxxxxxxxxx>
> Date: 2011/11/7
> Subject: Re: [Bug 865387] Re: wrong currency rounding
> To: Lorenzo Battistini <lorenzo.battistini@xxxxxxxxxxx>
> Cc: openerp-expert-accounting@xxxxxxxxxxxxxxxxxxx
> 
> On 11/06/2011 06:42 PM, Lorenzo Battistini wrote:
> > I have one more doubt about floats: how could I manage this
> > 
> >>>> round(2.675, 2)
> > 
> > 2.67
> 
> The key idea here is that you should not be rounding the decimal value
> to a smaller number of decimal digits directly, because the
> representational bias will have too big an influence.
> The error, as you probably saw, comes from the fact that 2.675 cannot be
> represented exactly as a floating point, and the closest IEEE 754
> representation is "2.674999...", which rounds logically to 2.67.
> 
> Instead, you should round to an integer to minimize the representation
> bias, based on the precision you're looking for.
> For example, if you want a precision of 2 decimal digits, you'll
> multiply the float value by 100, round to the closest integer, then
> divide by 100 again. That new result will be an IEEE-754 representation
> that is close enough to the x-digit decimal precision to be represented
> correctly.
> It could be 2.679999999... or 2.680000001.., but in all cases an amount
> that will always be rounded to 2.68 for printing/storing purposes.
> 
> >>> print round(2.675 * 100) / 100
> 
> 2.68
> 
> >>> print "%.25f" % (round(2.675 / 0.01) * 0.01,)
> 
> 2.6800000000000001598721155
> 
> This is exactly what res.currency.round() does, too.
> 
> We should probably provide generic round(value,precision) and
> is_zero(value,precision) methods in our builtin tools, as those in
> res.currency are tied to a currency record (or at least an object with a
> 'rounding' attribute)
> 
> Hope this helps...
> 
> _______________________________________________
> Mailing list: https://launchpad.net/~openerp-expert-accounting
> Post to     : openerp-expert-accounting@xxxxxxxxxxxxxxxxxxx
> Unsubscribe : https://launchpad.net/~openerp-expert-accounting
> More help   : https://help.launchpad.net/ListHelp
-- 
Best Regards

ChriCar Beteiligungs- und Beratungs- GmbH
http://www.chricar.at/ChriCar/index.html
Dr. Ferdinand Gassauer
Official Tiny Partner


References