Project

General

Profile

Actions

Feature #13420

closed

Integer#{round,floor,ceil,truncate} should always return an integer, not a float

Added by stomar (Marcus Stollsteimer) over 7 years ago. Updated over 7 years ago.

Status:
Closed
Target version:
-
[ruby-core:80645]

Description

The current behavior of Integer#{round,floor,ceil,truncate} produces wrong results for large integers.

In the case of a positive precision argument, these methods return the receiver converted to a float, effectively doing the same as to_f.

2.round(1)  # => 2.0

This leads to errors for large integers:

(10**25).round(2).to_i  # => 10000000000000000905969664
(10**400).round(2)      # => Infinity

Mathematically speaking, the value of an integer should not be changed by #round, #floor, #ceil, or #truncate, regardless of the precision (when positive). An integer rounded to e.g. 2 decimal digits is still the same (and exact) integer.

The desired behavior should be to keep precision as high as possible by not needlessly converting to Float.

The provided patch fixes these methods to return self for positive precision argument, similar to the behavior without a specified precision, i.e. precision 0.


Files

0001-Integer-round-floor-ceil-truncate.patch (7.83 KB) 0001-Integer-round-floor-ceil-truncate.patch stomar (Marcus Stollsteimer), 04/11/2017 06:31 AM

Related issues 1 (0 open1 closed)

Related to Ruby master - Bug #12780: BigDecimal#round returns different types depending on argumentClosedmrkn (Kenta Murata)Actions

Updated by nobu (Nobuyoshi Nakada) over 7 years ago

Indeed.
And documents?

Actions #2

Updated by stomar (Marcus Stollsteimer) over 7 years ago

  • File deleted (0001-Integer-round-floor-ceil-truncate.patch)
Actions #4

Updated by mrkn (Kenta Murata) over 7 years ago

  • Related to Bug #12780: BigDecimal#round returns different types depending on argument added

Updated by stomar (Marcus Stollsteimer) over 7 years ago

The patch has been updated to also include doc changes.

Any thoughts on this?

Updated by stomar (Marcus Stollsteimer) over 7 years ago

nobu, does this mean "Nice. Go ahead and apply!"?

(I fear I'm not too familiar with the ways around here, yet.)

And I noticed that while Integer#{floor,ceil,truncate} accept an ndigits argument only since recently (Ruby 2.4), Integer#round has this option and the behavior of returning a float for quite some time, and it's also in the specs (spec/rubyspec/core/integer/round_spec.rb). I guess they would need to get updated.

Updated by nobu (Nobuyoshi Nakada) over 7 years ago

  • Status changed from Open to Assigned
  • Assignee set to stomar (Marcus Stollsteimer)

stomar (Marcus Stollsteimer) wrote:

nobu, does this mean "Nice. Go ahead and apply!"?

Yes, of course.

And I noticed that while Integer#{floor,ceil,truncate} accept an ndigits argument only since recently (Ruby 2.4), Integer#round has this option and the behavior of returning a float for quite some time, and it's also in the specs (spec/rubyspec/core/integer/round_spec.rb). I guess they would need to get updated.

Indeed, it needs a version guard.

Actions #9

Updated by stomar (Marcus Stollsteimer) over 7 years ago

  • Status changed from Assigned to Closed

Applied in changeset trunk|r58586.


make Integer#{round,floor,ceil,truncate} always return integer

  • numeric.c (int_round): return integer (self) instead of float
    for Integer#round with positive ndigits argument, because
    conversion to float introduces errors for large integers.

  • numeric.c (int_floor): ditto for Integer#floor.

  • numeric.c (int_ceil): ditto for Integer#ceil.

  • numeric.c (int_truncate): ditto for Integer#truncate.

  • test/ruby/test_integer.rb: adjust test cases and add some more.

[ruby-core:80645] [Bug #13420]

Updated by stomar (Marcus Stollsteimer) over 7 years ago

Applied.

I opened a PR for the specs: https://github.com/ruby/spec/pull/436 [merged]

Should I add a comment in NEWS or not? [done]

Updated by Eregon (Benoit Daloze) over 7 years ago

stomar (Marcus Stollsteimer) wrote:

Applied.
I opened a PR for the specs: https://github.com/ruby/spec/pull/436

Thanks!

Should I add a comment in NEWS or not?

Yes, I think the rule is to add a NEWS entry for every user-visible behavior change.

Actions #12

Updated by usa (Usaku NAKAMURA) over 7 years ago

  • Tracker changed from Bug to Feature
Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0