Eneko Alonso

un Navarro en California

Projects

¿Eres español y vives fuera de España? ¿Estás pensando en salir una temporada a trabajar o estudiar en el extranjero? Si es así, no dejes de visitar Spaniards.es, la Comunidad de Españoles en el Mundo
spaniards.es

Recent comments

15:22 America/Los_Angeles


Banker's Rounding and Float Point Rounding

Banker's Rounding is a rounding system apparently used by bankers. I say apparently because our finnacial software and any other finnancial software I have seen does not use it (please correct me if I am wrong).

How does Banker's rounding system work? Well, it is like normal rounding, but when the number to round ends in 5, it doesn't round up always. It rounds to the closest even number.

For example, in normal rounding:

  • NormalRound(2.4) = 2
  • NormalRound(2.5) = 3
  • NormalRound(3.4) = 3
  • NormalRound(3.5) = 4

But in Banker's rounding:

  • BankersRound(2.4) = 2
  • BankersRound(2.5) = 2  // Here is the problem!!
  • BankersRound(3.4) = 3
  • BankersRound(3.5) = 4

This issue becomes very important when one develops finnancial software. Money is money and no one wants to loose a single penny. Beisdes that, the bigger problem is when balancing account. You don't want to get a message saying something is out of balance by a penny.

For some reason Delphi uses Bankers method by default. So you have to pay attention when programming. Otherwise you can make a mess.

But it gets even worst

Let's play with other float point numbers! As you may remember from College, float point is not accurate. It simply can't be! The way numbers are stored and processed on a chip makes it impossible to work with accurate numbers.

For example, 0.15 can not be represented as that in float point. Instead, it's represented as 0.149999999999998 (the number of nines may vary). Man, don't ask me why this happens, because I may had a chance to answer you properly when I was in College but now my brain just explodes when I try to do things like these.

So this is a big issue. If you try to round 0.15 to the tenths, you will get 0.1 instead of 0.2. Crap!

For example, we had to round the amount 18.615 to dollars. You may try to multiply by a hundred and get 1861.5. Then you can just add 0.5 and truncate to get the rounded amount: 1861.5 + 0.5 = 1862.0. Once you have the integer part (1862) you could divide it by a hundred and you would get the right value: 18.62.

Well, let me tell you something. It does not work!

All functions like Trunc, Int or Floor have trouble with this. This is because the value 1861.5 is acctually stored as 1861.499999. When adding 0.5 we get 1861.999999 which its integer part is 1861. Wrong result.

So how do we fix this?

Well, the easiest solution is to add a correction amount. Of course this has to be so small it wont affect the results. This margin is the maximum amount by which A and B can differ and still be
considered the same value.

So by adding 0.000000000000001 to the amount before rounding you get the problem solved, although you introduce a little margin of error for other numbers (let's say we actually want to round 1861.499999999..., we would get the wrong value, but in this case is acceptable).

PS: This is not just a Delphi issue. This is a well known float point precission error. Other compilers may handle this situations different.

More info:
http://coding.derkeiler.com/Archive/Delphi/borland.public.delphi.languag...
http://www.experts-exchange.com/Programming/Languages/Pascal/Delphi/Q_21... (especially the last comment by BJThomsen)

eh? anybody uses floats for

eh? anybody uses floats for money?
in java you must use BigDecimal, in SQL Decimal,... so both the integer and cents are stored separately as ints and there is no rounding problems

Well... it sounds kind of

Well... it sounds kind of crazy, I know. In our DB we use all decimal, with fixed precision. Still you have to deal with precision rounding issues, but you don't get any float point problem.

On Delphi side we use floats. I don't think there is anything else available.

And there's the Currency

And there's the Currency type for VB...

Well, Delphi has a Currency

Well, Delphi has a Currency type too, but it is still a float point variable, with only 4 decimal precision (which makes it even worst, at least for us).

Post new comment

The content of this field is kept private and will not be shown publicly.
CAPTCHA
This question is for testing whether you are a human visitor and to prevent automated spam submissions.
Image CAPTCHA
Enter the characters shown in the image.