Rounding -- was [PHP] round to nearest 500?

Rounding -- was [PHP] round to nearest 500?

Post by tedd » Fri, 16 Feb 2007 02:30:31

t 8:40 PM +0100 2/13/07, Satyam wrote:

Satyam and Jon:

Actually, both of you are correct.

The bias in rounding comes from the concept of rounding down for
numbers 0-4 and rounding up for number 5-9. Please, let's take a
critical look at that premise.

For zero, as Jon claims, there is no rounding at all -- you don't do
anything. You can't include zero as one of the conditions that claims
to do something when it doesn't do anything. It doesn't do anything
to the data at all! So, to include zero in a rounding scheme is
fundamentally flawed. Satyam, put your objections on hold for a
moment and consider.

For values one to four, you round down. So, you have four conditions
where you actually do something to the data, you round down.

For values five to nine, you round up. So, you have five conditions
where you actually do something to the data, you round up.

If you do anything four times one way and five times the other,
you're going to introduce a bias.

So, how do you get around this?

One way is to use Statistical (Stochastic) rounding. It singles out
five as being the culprit for this bias. It uses the even/odd rule of
the preceding digit to determine which direction to round 5. If the
value is even, then it rounds up -- whereas if the value is odd, then
it rounds down. (or reverse the rounding, it doesn't matter as long
as you are consistent).

For all other values (1-4 and 6-9, note four each direction) the
typical rounding is observed.

Examples of it at work:

0.5 -> 1 (zero is treated as even -- see below *)
1.5 - >1
2.5 -> 3
3.5 -> 3
4.5 -> 5
5.5 ->5
6.5 -> 7
7.5 -> 7
8.5 -> 9
9.5 - 9

From this distribution (actually all you'll ever need to prove this),
you can see we have just as many cases that round up as we do that
round down -- thus, the aforementioned rounding bias has been
reduced. The negative range is just a mirror image.

Now, one can try to pump this algorithm through a PHP loop to see the
difference (as I've tried) but you'll find that there are rounding
errors (due to what Satyam said about computers representing decimal
numbers exactly) that will prohibit making the algorithm work as

For example, the "built-in" functions, such as intval(), do not work
the way you might expect them to work. Try using this statement:

$t =intval(($number - intval($number)) * 10);

It works fine if the number is 89441560.5 -- it returns 5.

However, if the number is 139690837.6 -- returns 5 instead of 6.

And the list goes on of examples where the result isn't quite what's expected.

If you look deeper into this, you'll find the rounding problem
doesn't really have a solution, but rather it's a compromise. I'm
sure that Rasmus Lendorf could shed some light on this -- remember
the "When is z != z?" argument I started many moons ago? I think this
is along the same lines.

Perhaps the round() function takes all this into account, but I don't
know and therein lies my suspicion.



*By definition, any number that can be divided by two and leaves no
remainder is even. Some say that the value is undefined, but for sake
of this argument, it's considered even. Besides, symmetry in nature
is more desirable.