[R] customize the step value
Duncan Murdoch
murdoch@dunc@n @end|ng |rom gm@||@com
Fri Oct 29 18:03:08 CEST 2021
On 29/10/2021 11:04 a.m., Martin Maechler wrote:
>>>>>> Duncan Murdoch
>>>>>> on Fri, 29 Oct 2021 09:07:31 -0400 writes:
>
> > On 29/10/2021 4:34 a.m., PIKAL Petr wrote:
> >> Hi
> >>
> >> One has to be careful when using fractions in seq step.
> >>
> >> Although it works for 0.5
> >>> (seq(0,10, .5) - round(seq(0,10,.5),2))==0
> >> [1] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
> >> TRUE
> >> [16] TRUE TRUE TRUE TRUE TRUE TRUE
> >>
> >> in case of 0.3 (or others) it does not always result in expected values (see
> >> FAQ 7.31 for explanation)
> >>
> >>> (seq(0,10, .3) - round(seq(0,10,.3),2))==0
> >> [1] TRUE TRUE TRUE FALSE TRUE TRUE FALSE TRUE TRUE FALSE TRUE TRUE
> >> [13] FALSE TRUE TRUE TRUE TRUE TRUE FALSE TRUE TRUE TRUE TRUE FALSE
> >> [25] FALSE TRUE TRUE TRUE TRUE TRUE TRUE FALSE TRUE TRUE
>
>
> > Petr is right, it's unsafe to use fractional values for the step. 0.5
> > works because it has a power of 2 in the denominator and so does the
> > start value, but it's easy to make mistakes when you rely on that (e.g.
> > changing the step size from 0.5 to 0.3 would break things).
>
> > A better idea is to modify a sequence of integers. For example, to get
> > 1.5 to 3.5 by 0.5, you can do (3:7)*0.5, and for 0 to 3 by 0.3, use
> > (0:10)*0.3.
>
>
> Well, but you will not get truly equidistant (to the last bit)
> sequences also by that and people who are not aware of
> FAQ 7.31 and its consequences do wrongly assume that
No, that would be impossible.
>
> length(unique(diff(seqVec))) == 1
>
> for any seqVec <- k * seq(....) # k a "scalar" (of length 1)
>
> but the reality of floating point arithmetic can be quite
> different than pure math :
>
> In this case and on my platform the two ways to construct the
> sequence are even identical:
>
>> identical((0:10)*0.3, seq(0, 3, by=.3))
> [1] TRUE
>> sv <- (0:10)*0.3
>> length(unique(diff(sv))) # you'd like |--> 1 (the number 0.3 !)
> [1] 5
But I suspect that's not guaranteed for every step size.
The really serious problem (which R tries hard to avoid, but again I
doubt it's guaranteed) is to ask for
seq(a, b, step = (b-a)/n)
for an integer n and get a sequence that stops one step early and
doesn't include b. For this case, I would always use the replacement
a + (0:n)*(b - a)/n
I suspect this is also not guaranteed to return b, but it is guaranteed
to return a value very close to it.
Duncan Murdoch
More information about the R-help
mailing list