# Rounding to nearest even: nio gem?

Is there a gem which makes it easy to round floats to the nearest even
digit, such that:

8.5.round(0) => 8
7.5.round(0) => 8
1.0345.round(3) => 1.034
1.0335.round(3) => 1.034

I have been reading the docs of the nio gem, but can’t find out how that
works; for example:

7.5.nio_write(Nio::Fmt.mode(:fix,0,:round=>:even)) => “8” (ok)
8.5.nio_write(Nio::Fmt.mode(:fix,0,:round=>:even)) => “9” (wrong)
1.0345.nio_write(Nio::Fmt.mode(:fix,3,:round=>:even)) => “1.034” (ok)
1.0335.nio_write(Nio::Fmt.mode(:fix,3,:round=>:even)) => “1.034” (ok)

I’m not sure I understand what exactly do you want to do, or why would
you want to do that.

You could try dividing the number by two, rounding, and multiplying by
two again. This should give you the results you want.

irb(main):014:0> ( 8.5 /2).round(0)*2
=> 8
irb(main):015:0> ( 7.5 /2).round(0)*2
=> 8
irb(main):016:0> ( 1.0345 /2).round(3)*2
=> 1.034
irb(main):017:0> ( 1.0335 /2).round(3)*2
=> 1.034
irb(main):018:0> ( 1.0355 /2).round(3)*2
=> 1.036
irb(main):019:0> ( 1.0354 /2).round(3)*2
=> 1.036

– Matma R.

On 2012-07-16 17:15, Bartosz Dziewoński wrote:

I’m not sure I understand what exactly do you want to do, or why would
you want to do that.

From: Rounding - Wikipedia :
Round half to even
A tie-breaking rule that is less biased is round half to even, namely:
If the fraction of y is 0.5, then q is the even integer nearest to y.
Thus, for example, +23.5 becomes +24, as does +24.5; while −23.5 becomes
−24, as does −24.5.
This method treats positive and negative values symmetrically, and is
therefore free of sign bias. More importantly, for reasonable
distributions of y values, the expected (average) value of the rounded
numbers is the same as that of the original numbers. However, this rule
will introduce a towards-zero bias for even numbers, and a
towards-infinity bias for odd ones.

=> 1.034
irb(main):018:0> ( 1.0355 /2).round(3)*2
=> 1.036
irb(main):019:0> ( 1.0354 /2).round(3)*2
=> 1.036

Great, but: this can go wrong, too:

(6.94/2).round(1)*2
=> 7.0
(6.93/2).round(1)*2
=> 7.0

The point is that I want unbiased rounding of values that are resulting
from physical measurements; when you can read a measure to 1 decimal,
say 105.5, 104.7, 105.1, 104.9, 104.5, et cetera, and you round these
values to 0 decimals the standard ruby way, then all values ending in .5
will be rounded up; this causes a bias in the average, since actually
chances are equal that 104.5 is either 104 or 105. One way to prevent
this bias is by rounding to the nearest even digit.