[ruby-core:93931] [Ruby master Feature#16021] floor/ceil/round/truncate should accept a :step argument
From:
daniel@...42.com
Date:
2019-07-26 13:22:33 UTC
List:
ruby-core #93931
Issue #16021 has been updated by Dan0042 (Daniel DeLorme).
shyouhei (Shyouhei Urabe) wrote:
> Dan0042 (Daniel DeLorme) wrote:
> > Equivalent to e.g. `((num / step.to_f).round * step)`
> > =
> > ``` ruby
> > 12.3456.floor(step: 0.2) #=3D> 12.2
> > ```
> =
> Can I ask you what do you expect for `12.3456.floor(step: 0.0002)` then?
Good point, I see what you mean. I would expect 12.3456 but because of floa=
t imprecision we get 12.3454 using the above formula. Of course that's the =
gotcha with *any* float operations. Maybe I should have said *logically equ=
ivalent* to ((num / step.to_f).round * step)
There are implementation workarounds, e.g.
``` ruby
(12.3456 / 0.0002).next_float.floor * 0.0002 #=3D>12.345600000000001
(12.3456 / 0.0002) .round * 0.0002 #=3D>12.345600000000001
(12.3456 / 0.0002).prev_float.ceil * 0.0002 #=3D>12.345600000000001
```
Or the new, magical `fix_float` method! :-) (half-jesting)
``` ruby
class Float
def fix_float(sensitivity=3D6)
n =3D next_float
return n if n.to_s.size < self.to_s.size - sensitivity
p =3D prev_float
return p if p.to_s.size < self.to_s.size - sensitivity
return self
end
end
(12.3456 / 0.0002) #=3D> 61727.999999=
99999
(12.3456 / 0.0002).fix_float #=3D> 61728.0
((12.3456 / 0.0002).fix_float.floor * 0.0002).fix_float #=3D>12.3456
```
----------------------------------------
Feature #16021: floor/ceil/round/truncate should accept a :step argument
https://bugs.ruby-lang.org/issues/16021#change-80060
* Author: Dan0042 (Daniel DeLorme)
* Status: Feedback
* Priority: Normal
* Assignee: =
* Target version: =
----------------------------------------
These rounding methods currently accept a number of (decimal) digits, but a=
more general mechanism would allow rounding to the nearest =BC, multiple o=
f 5, etc.
Equivalent to e.g. `((num / step.to_f).round * step)`
``` ruby
12.3456.floor(step: 0.2) #=3D> 12.2
12.3456.round(step: 0.2) #=3D> 12.4
12.3456.floor(step: 0.2) #=3D> 12.4
12.3456.floor(step: 0.2) #=3D> 12.2
```
IMHO this should also apply to Time#floor/round/ceil
``` ruby
Time.now.floor(step: 3600) #=3D> current hour
Time.now.round(step: 3600) #=3D> nearest hour
Time.now.ceil(step: 3600) #=3D> next hour
```
We can also consider that instead of `:step` , `:by` might be quite readabl=
e.
``` ruby
12.3456.round(by: 0.2) #=3D> 12.4
```
-- =
https://bugs.ruby-lang.org/
Unsubscribe: <mailto:ruby-core-request@ruby-lang.org?subject=3Dunsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>