Beefy Boxes and Bandwidth Generously Provided by pair Networks
Keep It Simple, Stupid

Re: Strange int() result

by davido (Archbishop)
on Jun 18, 2014 at 18:38 UTC ( #1090328=note: print w/replies, xml ) Need Help??

in reply to Strange int() result

You didn't mention where your data comes from. One problem is that as soon as you import data as floating point, it is stored in an internal format that loses precision if it cannot be represented precisely as n/2^m (edited). Whatever the conversion, do it as early as possible, as the first thing you do with your data before any other mathematical operation.

MJD suggests in his blog about Moonpig: a billing system that doesn't suck that because floating-point numbers are among the things that suck, the law of the Moonpig project states that "...all money amounts are integers. Each money amount is an integral number of “millicents”..."

The blog's discussion of handling of financial numbers is very helpful. Please do read it. I don't think I would touch financial data again without first browsing through it to refresh my memory.


Replies are listed 'Best First'.
Re^2: Strange int() result
by Your Mother (Bishop) on Jun 18, 2014 at 19:39 UTC

    The only shop I ever worked in where I had to touch the money code did this too. We used cents as the integer instead of millicents but same idea, just grainier precision.

    Also noticed MJD's note–

    Your account is currently past due! Pay the outstanding balance of $ 0 . 00 or we will be forced to refer your account for collection.

    I got this exact letter from American Express once so plenty of devs who have no business making this class of mistake do so anyway.

      I've had bills for amounts in the "few pennies" range; less than the value of the postage stamp. Back in the days when I paid via checks and snail mail, I recall on at least one (possibly more) occasion I intentionally sent a check rounded up to a dollar.

      This accomplished two things. First, it threw any possible round-off-error ball back into their court. And second, it gained me the minor satisfaction of getting the last word -- forcing a refund check in a silly-small amount.


      I twice got a similar letter, except the balance was $(0.01), meaning they owed me money. Turns out there was a bug in the Point of Sale software where the sales tax was rounded down for purchases and up for returns. I pointed it out after the first letter. The rest of that billing cycle I had no purchases, thus the second letter.

Re^2: Strange int() result
by Laurent_R (Canon) on Jun 18, 2014 at 20:32 UTC
    My main client is a very large telecoms operator (35 million mobile phone customers, not counting those in the foreign and overseas subsidiaries) in Europe and I am working a lot on their mobile phone billing system. All the financial amounts are stored internally in the database as euro cents integers, with input and output masks providing for two decimal places.

      Is euro-cents sufficient precision? In mjd's talk (and in his blog) he alludes to the fact that if you divide a term by a rate you'll end up with some rounding errors that are mitigated by millicents, and that in a larger scale might be best handled by microcents.


        Well, using euro cent integer is sufficient precision for storing into the database amounts that will be simply added (or subtracted in the case of discounts) at the end of the billing period to produce the invoice.

        But when a calculation such as a multiplication or a division is involved, then, yes, some amounts (billing rates in the catalog, for example) are indeed stored in integer "millicents" (multiplied by 1E5) in order to get the right value in the end. I actually participated in 2009 to a project where we changed the catalog tariffs from 3 to 5 decimal point precision because it was the only way to get the right amount in the final invoice without any rounding error. Typically, if the marketing was selling a subscription for, say, EUR 19.90 (VAT inclusive) per month, it was impossible to find a before-tax rate to be stored in the catalog that would lead to exactly 19.90 after applying the tax rate (we would get, for example, either 19.91 or 19.89 after rounding). With a five decimal place catalog, any 2 decimal-place amount could be reached after applying the VAT rate. But this is really a rounding issue, not exactly the same thing as the floating point versus integer arithmetic problem (even though they are somewhat related).

        In my experience rounding issues and date management issues are some of the worst problems plaguing regularly information technology for business management. In the case of rounding issues, my client had to go through three large successive projects over a period of more than two years before getting rid completely of these rounding problems. The overall cost of these 3 projects is far in excess of one million euros, perhaps closer to or even above two million euros. I don't know exactly because I know (more or less accurately) only about the direct IT costs (studies, development and tests), but a lot of work from non IT persons (people from business departments, marketing, support, customer relationship, management, accounting, finance, tax, auditing, revenue assurance, SOX compliance, etc.) is also involved.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://1090328]
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others exploiting the Monastery: (3)
As of 2018-03-20 23:50 GMT
Find Nodes?
    Voting Booth?
    When I think of a mole I think of:

    Results (262 votes). Check out past polls.