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

______________________________________________
R-help@r-project.org mailing list -- To UNSUBSCRIBE and more, see
https://stat.ethz.ch/mailman/listinfo/r-help
PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
and provide commented, minimal, self-contained, reproducible code.

Reply via email to