Velocity Reviews > Rounding a number to nearest even

# Rounding a number to nearest even

Thomas Dybdahl Ahle
Guest
Posts: n/a

 04-14-2008
On Fri, 2008-04-11 at 03:14 -0700, bdsatish wrote:
> The built-in function round( ) will always "round up", that is 1.5 is
> rounded to 2.0 and 2.5 is rounded to 3.0.
>
> If I want to round to the nearest even, that is
>
> my_round(1.5) = 2 # As expected
> my_round(2.5) = 2 # Not 3, which is an odd num
>
> I'm interested in rounding numbers of the form "x.5" depending upon
> whether x is odd or even. Any idea about how to implement it ?

This seams to work fine:
evenRound = lambda f: round(f/2.)*2

>>> [(f*.5, evenRound(f*.5)) for f in xrange(0,20)]

[(0.0, 0.0),(0.5, 0.0),
(1.0, 2.0), (1.5, 2.0), (2.0, 2.0), (2.5, 2.0),
(3.0, 4.0), (3.5, 4.0), (4.0, 4.0), (4.5, 4.0),
(5.0, 6.0), (5.5, 6.0), (6.0, 6.0), (6.5, 6.0),
(7.0, 8.0), (7.5, 8.0), (8.0, 8.0), (8.5, 8.0),
(9.0, 10.0), (9.5, 10.0)]

--
Best Regards,
Med Venlig Hilsen,
Thomas

Sjoerd Mullender
Guest
Posts: n/a

 04-15-2008
Thomas Dybdahl Ahle wrote:
> On Fri, 2008-04-11 at 03:14 -0700, bdsatish wrote:
>> The built-in function round( ) will always "round up", that is 1.5 is
>> rounded to 2.0 and 2.5 is rounded to 3.0.
>>
>> If I want to round to the nearest even, that is
>>
>> my_round(1.5) = 2 # As expected
>> my_round(2.5) = 2 # Not 3, which is an odd num
>>
>> I'm interested in rounding numbers of the form "x.5" depending upon
>> whether x is odd or even. Any idea about how to implement it ?

>
> This seams to work fine:
> evenRound = lambda f: round(f/2.)*2
>
>>>> [(f*.5, evenRound(f*.5)) for f in xrange(0,20)]

> [(0.0, 0.0),(0.5, 0.0),
> (1.0, 2.0), (1.5, 2.0), (2.0, 2.0), (2.5, 2.0),
> (3.0, 4.0), (3.5, 4.0), (4.0, 4.0), (4.5, 4.0),
> (5.0, 6.0), (5.5, 6.0), (6.0, 6.0), (6.5, 6.0),
> (7.0, 8.0), (7.5, 8.0), (8.0, 8.0), (8.5, 8.0),
> (9.0, 10.0), (9.5, 10.0)]
>

No, this does not work:
>>> [(f*.25, evenRound(f*.25)) for f in xrange(0,20)]

[(0.0, 0.0), (0.25, 0.0), (0.5, 0.0), (0.75, 0.0), (1.0, 2.0), (1.25,
2.0), (1.5, 2.0), (1.75, 2.0), (2.0, 2.0), (2.25, 2.0), (2.5, 2.0),
(2.75, 2.0), (3.0, 4.0), (3.25, 4.0), (3.5, 4.0), (3.75, 4.0), (4.0,
4.0), (4.25, 4.0), (4.5, 4.0), (4.75, 4.0)]

x.75 should be rounded up.

--
Sjoerd Mullender

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.7 (GNU/Linux)
Comment: Using GnuPG with Fedora - http://enigmail.mozdev.org

iQCVAwUBSARzyD7g04AjvIQpAQJALwP+Jp6FWbfgxI9JhOb07T cV5J7Hoyf2js/5
en0imvL7UkZ26JkM5M+2oOzN3ouydXo8fyw/TlYSgICqhI1rSKZBy3UqgsqaxYCm
lfucE4GSE46+y8G/OO8SB3ym2OnJBKNqkSuCYH2k3mDjrae802MDAFaeEkodK2wE
SQHZ9uTXY6E=
=IHSB
-----END PGP SIGNATURE-----

Chris
Guest
Posts: n/a

 04-15-2008
On Apr 15, 11:22*am, Sjoerd Mullender <(E-Mail Removed)> wrote:
> Thomas Dybdahl Ahle wrote:
> > On Fri, 2008-04-11 at 03:14 -0700, bdsatish wrote:
> >> The built-in function round( ) will always "round up", that is 1.5 is
> >> rounded to 2.0 and 2.5 is rounded to 3.0.

>
> >> If I want to round to the nearest even, that is

>
> >> my_round(1.5) = 2 * * * *# As expected
> >> my_round(2.5) = 2 * * * *# Not 3, which is an odd num

>
> >> I'm interested in rounding numbers of the form "x.5" depending upon
> >> whether x is odd or even. Any idea about how to implement it ?

>
> > This seams to work fine:
> > evenRound = lambda f: round(f/2.)*2

>
> >>>> [(f*.5, evenRound(f*.5)) for f in xrange(0,20)]

> > [(0.0, 0.0),(0.5, 0.0),
> > (1.0, 2.0), (1.5, 2.0), (2.0, 2.0), (2.5, 2.0),
> > (3.0, 4.0), (3.5, 4.0), (4.0, 4.0), (4.5, 4.0),
> > (5.0, 6.0), (5.5, 6.0), (6.0, 6.0), (6.5, 6.0),
> > (7.0, 8.0), (7.5, 8.0), (8.0, 8.0), (8.5, 8.0),
> > (9.0, 10.0), (9.5, 10.0)]

>
> No, this does not work:>>> [(f*.25, evenRound(f*.25)) for f in xrange(0,20)]
>
> [(0.0, 0.0), (0.25, 0.0), (0.5, 0.0), (0.75, 0.0), (1.0, 2.0), (1.25,
> 2.0), (1.5, 2.0), (1.75, 2.0), (2.0, 2.0), (2.25, 2.0), (2.5, 2.0),
> (2.75, 2.0), (3.0, 4.0), (3.25, 4.0), (3.5, 4.0), (3.75, 4.0), (4.0,
> 4.0), (4.25, 4.0), (4.5, 4.0), (4.75, 4.0)]
>
> x.75 should be rounded up.
>
> --
> Sjoerd Mullender
>
> *signature.asc

even is closer to even.75 than even+1.25. Why should it be rounded
up ?

colas.francis@gmail.com
Guest
Posts: n/a

 04-15-2008
On 14 avr, 20:02, Thomas Dybdahl Ahle <(E-Mail Removed)> wrote:
> On Fri, 2008-04-11 at 03:14 -0700, bdsatish wrote:
> > The built-in function round( ) will always "round up", that is 1.5 is
> > rounded to 2.0 and 2.5 is rounded to 3.0.

>
> > If I want to round to the nearest even, that is

>
> > my_round(1.5) = 2 # As expected
> > my_round(2.5) = 2 # Not 3, which is an odd num

>
> > I'm interested in rounding numbers of the form "x.5" depending upon
> > whether x is odd or even. Any idea about how to implement it ?

>
> This seams to work fine:
> evenRound = lambda f: round(f/2.)*2

That was the solution I proposed first but it is inadequate since the
op does not want 3 to be rounded to 4.
If you're interested in this discussion, I kindly suggest you read the
whole thread: many interesting proposals and discussions have ensued.

Chris
Guest
Posts: n/a

 04-15-2008
On Apr 15, 11:47*am, Duncan Booth <(E-Mail Removed)>
wrote:
> Chris <(E-Mail Removed)> wrote:
> > even is closer to even.75 than even+1.25. *Why should it be rounded
> > up ?

>
> Because the OP wants to round values to the nearest integer. Only values of
> the form 'x.5' which have two nearest values use 'nearest even' to
> disambiguate the result.
>
> Seehttp://en.wikipedia.org/wiki/Rounding#Round-to-even_method
>
> That's the way I was taught to round numbers when at primary school.

My bad, didn't see he only wanted for halves and handle others as
normal.

Chris
Guest
Posts: n/a

 04-15-2008
On Apr 15, 12:33*pm, Chris <(E-Mail Removed)> wrote:
> On Apr 15, 11:47*am, Duncan Booth <(E-Mail Removed)>
> wrote:
>
> > Chris <(E-Mail Removed)> wrote:
> > > even is closer to even.75 than even+1.25. *Why should it be rounded
> > > up ?

>
> > Because the OP wants to round values to the nearest integer. Only values of
> > the form 'x.5' which have two nearest values use 'nearest even' to
> > disambiguate the result.

>
> > Seehttp://en.wikipedia.org/wiki/Rounding#Round-to-even_method

>
> > That's the way I was taught to round numbers when at primary school.

>
> My bad, didn't see he only wanted for halves and handle others as
> normal.

My contribution then:

def my_round(x):
if x < 0:
NEG = 1
x = -x
else:
NEG = 0
if not x%.5 and not int(x)%2:
if NEG: return -round(x-.1)
return round(x-.1)
elif not x%.5 and int(x)%2:
if NEG: return -round(x+.1)
return round(x+.1)
elif NEG:
return round(-x)
else:
return round(x)

[(f*.25, my_round(f*.25)) for f in xrange(-20,20)]

[(-5.0, -5.0), (-4.75, -5.0), (-4.5, -4.0), (-4.25, -4.0), (-4.0,
-4.0), (-3.75, -4.0), (-3.5, -4.0), (-3.25, -3.0), (-3.0, -3.0),
(-2.75, -3.0), (-2.5, -2.0), (-2.25, -2.0), (-2.0, -2.0), (-1.75,
-2.0), (-1.5, -2.0), (-1.25, -1.0), (-1.0, -1.0), (-0.75, -1.0),
(-0.5, 0.0), (-0.25, 0.0), (0.0, 0.0), (0.25, 0.0), (0.5, 0.0), (0.75,
1.0), (1.0, 1.0), (1.25, 1.0), (1.5, 2.0), (1.75, 2.0), (2.0, 2.0),
(2.25, 2.0), (2.5, 2.0), (2.75, 3.0), (3.0, 3.0), (3.25, 3.0), (3.5,
4.0), (3.75, 4.0), (4.0, 4.0), (4.25, 4.0), (4.5, 4.0), (4.75, 5.0)]

Arnaud Delobelle
Guest
Posts: n/a

 04-15-2008
On 11 Apr, 21:29, Gabriel Genellina <(E-Mail Removed)> wrote:
> ... If the numbers to be rounded come from a
> measurement, the left column is not just a number but the representant
> of an interval (as Mikael said, the're quantized). 2.3 means that the
> measurement was closer to 2.3 than to 2.2 or 2.4 - that is, [2.25,
> 2.35) (it doesn't really matter which side is open or closed). It is
> this "interval" behavior that forces the "round-to-even-on-halves"
> rule.
> So, the numbers 1.6-2.4 on the left column cover the interval [1.55,
> 2.45) and there is no doubt that they should be rounded to 2.0 because
> all of them are closer to 2.0 than to any other integer. Similarly
> [2.55, 3.45) are all rounded to 3.
> But what to do with [2.45, 2.55), the interval represented by 2.5? We
> can assume a uniform distribution here even if the whole distribution
> is not (because we're talking of the smallest measurable range). So
> half of the time the "true value" would have been < 2.5, and we should
> round to 2. And half of the time it's > 2.5 and we should round to 3.
> Rounding always to 3 introduces a certain bias in the process.
> Rounding randomly (tossing a coin, by example) would be fair, but
> people usually prefer more deterministic approaches. If the number of
> intervals is not so small, the "round even" rule provides a way to
> choose from that two possibilities with equal probability.
> So when we round 2.5 we are actually rounding an interval which could
> be equally be rounded to 2 or to 3, and the same for 3.5, 4.5 etc. If
> the number of such intervals is big, choosing the even number helps to
> make as many rounds up as rounds down.
> If the number of such intervals is small, *any* apriori rule will
> introduce a bias.

Great explanation!

--
Arnaud

Lie
Guest
Posts: n/a

 04-17-2008
On Apr 13, 7:20 pm, Steve Holden <(E-Mail Removed)> wrote:
> Lie wrote:
> > On Apr 12, 3:44 am, hdante <(E-Mail Removed)> wrote:

> [snip]
>
> > In short, choosing that x.0 is rounded down and x.5 is rounded up is
> > arbitrary but not without a reason.

>
> Don't "arbitrary" and "not without a reason" directly contradict one
> another?
>

The same as choosing between round-half-odd and round-half-even,
arbitrary but not without a reason.

Language-wise it is a contradiction. In a loose semantic meaning, it
means there is no strong reason for choosing one above the other
(round-up vs round down and round-half-even vs round-half-odd) but
there are slight advantages on one that would seems silly to be
mentioned as the main reason, so arbitrary but not without reason.

On Apr 13, 9:28 pm, Mark Dickinson <(E-Mail Removed)> wrote:
> On Apr 13, 4:18 am, Lie <(E-Mail Removed)> wrote:
> [...]
>
> > it and there is nothing else in it, but in the second number range
> > (barely above 1 to 2) the number 1.0 is not included while the number
> > 2.0 is contained in it, clearly not a clean separation of numbers in
> > the form of y.x where y is pre-determined and x is variable from other
> > possible values of y.

>
> Have you considered the fact that the real numbers of
> the form 1.xxxxx... are those in the range [1.0, 2.0],
> including *both* endpoints? That is, 2.0 = 1.999999...
> Similarly, the midpoint of this range can be written
> both in the form 1.500000... and 1.499999...

No, you can only include one of the endpoints, because if both
endpoints are included, the integers would be a included twice on the
various sets of numbers, e.g. in [1.0 - 2.0] and [2.0 - 3.0] the
number 2.0 is included in both ranges, you can't be a member of both
ranges because that means if you have a "fair" random number
generator, the possibility of integral number to appear would be twice
the possibility of non-integral numbers, well that's not a fair random
number generator isn't it?

> This is relevant if you think of rounding as an operation
> on *decimal representations* of real numbers rather than
> as an operation on real numbers themselves. I'm not sure
> which point of view you're taking here.

Actually, I'm on the side that think numbers should never be
rounded[1], except for a final representation to human viewer who
should be made aware that the numbers in the presentation should never
be used for further calculation, as they are only informative but not
normative. In this view, the exact rounding method is irrelevant as
numbers used for calculation are never rounded while at the lower
level the amount of change caused by rounding has become irrelevant
because of the extra precision used. In short, if the rounding
algorithm causes you a trouble in the particular field, increase the
precision.

[1] As computers do have limitation on storage of real number
representation, this statement means that real numbers should be kept
as precise as the hardware allows or to use decimal and allow extra
precision generously.

> Either way, your arguments don't change the fact that the
> average rounding error is strictly positive for positive
> quantized results, under round-half-away-from-zero.

If you include negative numbers, the ARE is zero on round-half-away-
from-zero, not in round-up though.