openerp-expert-accounting team mailing list archive
-
openerp-expert-accounting team
-
Mailing list archive
-
Message #01409
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