Forum: Ruby ruby rounding?

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Kyle S. (Guest)
on 2007-04-11 22:18
(Received via mailing list)
Something interesting came up at work concerning rounding.  Notably,
that the round procedure in vb.net was good for stats (round to even),
but since what the programmers expected (symmetric arithmetic
rounding) was different, some edge cases were failing their tests.

This got me thinking, what does Ruby use for rounding?  It turns out
(example below) it's symmetric arithmetic rounding.  But the methods
in C's math.h give the programmer a choice of which rounding method to
use.

Since there's so much development going on in Ruby currently, maybe
something like this could be/should be added.

See http://en.wikipedia.org/wiki/Rounding for details on the methods

--Kyle
-------------
Using this array in several languages:
[-5.0, -4.5, -4.0, -3.5, -3.0, -2.5, -2.0, -1.5, -1.0, -0.5, 0.0, 0.5,
1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5]

rounded:
ruby
[-5, -5, -4, -4, -3, -3, -2, -2, -1, -1, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5]

gcc
[-5, -5, -4, -4, -3, -3, -2, -2, -1, -1, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5]


vbs (ugly but I had it on hand)
[-5, -4, -4, -4, -3, -2, -2, -2, -1, 0, 0, 0, 1, 2, 2, 2, 3, 4, 4, 4]

vb.net (again ugly, but on hand)
[-5, -4, -4, -4, -3, -2, -2, -2, -1, 0, 0, 0, 1, 2, 2, 2, 3, 4, 4, 4]
unknown (Guest)
on 2007-04-12 00:30
(Received via mailing list)
On Apr 11, 11:17 am, "Kyle S." <removed_email_address@domain.invalid> wrote:
> Since there's so much development going on in Ruby currently, maybe
> something like this could be/should be added.

You could always create your own :).  Here is a something that I put
together.  There may be a better method.  The weird thing in the code
with comparing the remainder to 1e-9 is to deal with floating point
precision issues.  This may or may not be appropriate... I'm not a
rounding expert but it's worked in applications that I developed.

Anyway, here it is:

class Numeric
  def even_round()
    if ((self.truncate % 2 == 0) and ((self.remainder(1).abs -
0.5).abs < 1e-9))
      # integer portion is even and on 0.5 threshold
      self.truncate
    else
      # integer portion is odd or not on 0.5 threshold
      self.round
    end
  end
end

irb(main):012:0> a =  [-5.0, -4.5, -4.0, -3.5, -3.0, -2.5, -2.0, -1.5,
-1.0, -0.5, 0.0, 0.5,  1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5]
=> [-5.0, -4.5, -4.0, -3.5, -3.0, -2.5, -2.0, -1.5, -1.0, -0.5, 0.0,
0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5]
irb(main):013:0> a.map {|e| e.even_round}
=> [-5, -4, -4, -4, -3, -2, -2, -2, -1, 0, 0, 0, 1, 2, 2, 2, 3, 4, 4,
4]
Chris S. (Guest)
on 2007-04-12 01:21
(Received via mailing list)
On Apr 11, 2:25 pm, removed_email_address@domain.invalid wrote:
> On Apr 11, 11:17 am, "Kyle S." <removed_email_address@domain.invalid> wrote
>
> You could always create your own :).  Here is a something that I put
> together.  There may be a better method.  The weird thing in the code
> with comparing the remainder to 1e-9 is to deal with floating point
> precision issues.  This may or may not be appropriate... I'm not a
> rounding expert but it's worked in applications that I developed.

I could be wrong, but I think this is what the constant Float::EPSILON
is for.  Where I'm sitting it's 2.22044604925031e-16.

Chris
unknown (Guest)
on 2007-04-12 09:45
(Received via mailing list)
On Apr 11, 2:19 pm, "Chris S." <removed_email_address@domain.invalid> wrote:
> I could be wrong, but I think this is what the constant Float::EPSILON
> is for.  Where I'm sitting it's 2.22044604925031e-16.

Excellent - thanks for the info.
This topic is locked and can not be replied to.