

Dear all,
I a bit unsure, whether this qualifies as a bug, but it is definitly a strange behaviour. That why I wanted to discuss it.
With the following function, I want to test for evenly space numbers, starting from anywhere.
.is_continous_evenly_spaced < function(n){
if(length(n) < 2) return(FALSE)
n < n[order(n)]
n < n  min(n)
step < n[2]  n[1]
test < seq(from = min(n), to = max(n), by = step)
if(length(n) == length(test) &&
all(n == test)){
return(TRUE)
}
return(FALSE)
}
> .is_continous_evenly_spaced(c(1,2,3,4))
[1] TRUE
> .is_continous_evenly_spaced(c(1,3,4,5))
[1] FALSE
> .is_continous_evenly_spaced(c(1,1.1,1.2,1.3))
[1] FALSE
I expect the result for 1 and 2, but not for 3. Upon Investigation it turns out, that n == test is TRUE for every pair, but not for the pair of 0.2.
The types reported are always double, however n[2] == 0.1 reports FALSE as well.
The whole problem is solved by switching from all(n == test) to all(as.character(n) == as.character(test)). However that is weird, isn�t it?
Does this work as intended? Thanks for any help, advise and suggestions in advance.
Best regards,
Felix
[[alternative HTML version deleted]]
______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/rdevel


El vie., 31 ago. 2018 a las 15:10, Felix Ernst
(< [hidden email]>) escribió:
>
> Dear all,
>
> I a bit unsure, whether this qualifies as a bug, but it is definitly a strange behaviour. That why I wanted to discuss it.
>
> With the following function, I want to test for evenly space numbers, starting from anywhere.
>
> .is_continous_evenly_spaced < function(n){
> if(length(n) < 2) return(FALSE)
> n < n[order(n)]
> n < n  min(n)
> step < n[2]  n[1]
> test < seq(from = min(n), to = max(n), by = step)
> if(length(n) == length(test) &&
> all(n == test)){
> return(TRUE)
> }
> return(FALSE)
> }
>
> > .is_continous_evenly_spaced(c(1,2,3,4))
> [1] TRUE
> > .is_continous_evenly_spaced(c(1,3,4,5))
> [1] FALSE
> > .is_continous_evenly_spaced(c(1,1.1,1.2,1.3))
> [1] FALSE
>
> I expect the result for 1 and 2, but not for 3. Upon Investigation it turns out, that n == test is TRUE for every pair, but not for the pair of 0.2.
>
> The types reported are always double, however n[2] == 0.1 reports FALSE as well.
>
> The whole problem is solved by switching from all(n == test) to all(as.character(n) == as.character(test)). However that is weird, isn’t it?
>
> Does this work as intended? Thanks for any help, advise and suggestions in advance.
I guess this has something to do with how the sequence is built and
the inherent error of floating point arithmetic. In fact, if you
return test minus n, you'll get:
[1] 0.000000e+00 0.000000e+00 2.220446e16 0.000000e+00
and the error gets bigger when you continue the sequence; e.g., this
is for c(1, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7):
[1] 0.000000e+00 0.000000e+00 2.220446e16 2.220446e16 4.440892e16
[6] 4.440892e16 4.440892e16 0.000000e+00
So, independently of this is considered a bug or not, instead of
length(n) == length(test) && all(n == test)
I would use the following condition:
isTRUE(all.equal(n, test))
Iñaki

Iñaki Ucar
______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/rdevel


Agreed that's it's rounding error, and all.equal would be the way to go.
I wouldn't call it a bug, it's simply part of working with floating point numbers, any language has the same issue.
And while we're at it, I think the function can be a lot shorter:
.is_continous_evenly_spaced < function(n){
length(n)>1 && isTRUE(all.equal(n[order(n)], seq(from=min(n), to=max(n), length.out = length(n))))
}
Cheers, Emil
El vie., 31 ago. 2018 a las 15:10, Felix Ernst
(< [hidden email]>) escribió:
>
> Dear all,
>
> I a bit unsure, whether this qualifies as a bug, but it is definitly a strange behaviour. That why I wanted to discuss it.
>
> With the following function, I want to test for evenly space numbers, starting from anywhere.
>
> .is_continous_evenly_spaced < function(n){
> if(length(n) < 2) return(FALSE)
> n < n[order(n)]
> n < n  min(n)
> step < n[2]  n[1]
> test < seq(from = min(n), to = max(n), by = step)
> if(length(n) == length(test) &&
> all(n == test)){
> return(TRUE)
> }
> return(FALSE)
> }
>
> > .is_continous_evenly_spaced(c(1,2,3,4))
> [1] TRUE
> > .is_continous_evenly_spaced(c(1,3,4,5))
> [1] FALSE
> > .is_continous_evenly_spaced(c(1,1.1,1.2,1.3))
> [1] FALSE
>
> I expect the result for 1 and 2, but not for 3. Upon Investigation it turns out, that n == test is TRUE for every pair, but not for the pair of 0.2.
>
> The types reported are always double, however n[2] == 0.1 reports FALSE as well.
>
> The whole problem is solved by switching from all(n == test) to all(as.character(n) == as.character(test)). However that is weird, isn’t it?
>
> Does this work as intended? Thanks for any help, advise and suggestions in advance.
I guess this has something to do with how the sequence is built and
the inherent error of floating point arithmetic. In fact, if you
return test minus n, you'll get:
[1] 0.000000e+00 0.000000e+00 2.220446e16 0.000000e+00
and the error gets bigger when you continue the sequence; e.g., this
is for c(1, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7):
[1] 0.000000e+00 0.000000e+00 2.220446e16 2.220446e16 4.440892e16
[6] 4.440892e16 4.440892e16 0.000000e+00
So, independently of this is considered a bug or not, instead of
length(n) == length(test) && all(n == test)
I would use the following condition:
isTRUE(all.equal(n, test))
Iñaki
>
> Best regards,
> Felix
>
>
> [[alternative HTML version deleted]]
>
> ______________________________________________
> [hidden email] mailing list
> https://stat.ethz.ch/mailman/listinfo/rdevel

Iñaki Ucar
______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/rdevel
______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/rdevel


FYI, more fun with floats:
> 0.1+0.1==0.2
[1] TRUE
> 0.1+0.1+0.1+0.1==0.4
[1] TRUE
> 0.1+0.1+0.1==0.3
[1] FALSE
> 0.1+0.1+0.1==0.1*3
[1] TRUE
> 0.3==0.1*3
[1] FALSE
¯\_(ツ)_/¯
But this is not R's fault. See: https://0.30000000000000004.comIñaki
El vie., 31 ago. 2018 a las 15:36, Iñaki Ucar
(< [hidden email]>) escribió:
>
> El vie., 31 ago. 2018 a las 15:10, Felix Ernst
> (< [hidden email]>) escribió:
> >
> > Dear all,
> >
> > I a bit unsure, whether this qualifies as a bug, but it is definitly a strange behaviour. That why I wanted to discuss it.
> >
> > With the following function, I want to test for evenly space numbers, starting from anywhere.
> >
> > .is_continous_evenly_spaced < function(n){
> > if(length(n) < 2) return(FALSE)
> > n < n[order(n)]
> > n < n  min(n)
> > step < n[2]  n[1]
> > test < seq(from = min(n), to = max(n), by = step)
> > if(length(n) == length(test) &&
> > all(n == test)){
> > return(TRUE)
> > }
> > return(FALSE)
> > }
> >
> > > .is_continous_evenly_spaced(c(1,2,3,4))
> > [1] TRUE
> > > .is_continous_evenly_spaced(c(1,3,4,5))
> > [1] FALSE
> > > .is_continous_evenly_spaced(c(1,1.1,1.2,1.3))
> > [1] FALSE
> >
> > I expect the result for 1 and 2, but not for 3. Upon Investigation it turns out, that n == test is TRUE for every pair, but not for the pair of 0.2.
> >
> > The types reported are always double, however n[2] == 0.1 reports FALSE as well.
> >
> > The whole problem is solved by switching from all(n == test) to all(as.character(n) == as.character(test)). However that is weird, isn’t it?
> >
> > Does this work as intended? Thanks for any help, advise and suggestions in advance.
>
> I guess this has something to do with how the sequence is built and
> the inherent error of floating point arithmetic. In fact, if you
> return test minus n, you'll get:
>
> [1] 0.000000e+00 0.000000e+00 2.220446e16 0.000000e+00
>
> and the error gets bigger when you continue the sequence; e.g., this
> is for c(1, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7):
>
> [1] 0.000000e+00 0.000000e+00 2.220446e16 2.220446e16 4.440892e16
> [6] 4.440892e16 4.440892e16 0.000000e+00
>
> So, independently of this is considered a bug or not, instead of
>
> length(n) == length(test) && all(n == test)
>
> I would use the following condition:
>
> isTRUE(all.equal(n, test))
>
> Iñaki
>
> >
> > Best regards,
> > Felix
> >
> >
> > [[alternative HTML version deleted]]
> >
> > ______________________________________________
> > [hidden email] mailing list
> > https://stat.ethz.ch/mailman/listinfo/rdevel>
>
>
> 
> Iñaki Ucar

Iñaki Ucar
______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/rdevel


how about
is_evenly_spaced < function(x,...) all.equal(diff(sort(x)),...)
(use ellipsis to set tolerance if necessary)
Op vr 31 aug. 2018 om 15:46 schreef Emil Bode < [hidden email]>:
> Agreed that's it's rounding error, and all.equal would be the way to go.
> I wouldn't call it a bug, it's simply part of working with floating point
> numbers, any language has the same issue.
>
> And while we're at it, I think the function can be a lot shorter:
> .is_continous_evenly_spaced < function(n){
> length(n)>1 && isTRUE(all.equal(n[order(n)], seq(from=min(n), to=max(n),
> length.out = length(n))))
> }
>
> Cheers, Emil
>
> El vie., 31 ago. 2018 a las 15:10, Felix Ernst
> (< [hidden email]>) escribió:
> >
> > Dear all,
> >
> > I a bit unsure, whether this qualifies as a bug, but it is definitly
> a strange behaviour. That why I wanted to discuss it.
> >
> > With the following function, I want to test for evenly space
> numbers, starting from anywhere.
> >
> > .is_continous_evenly_spaced < function(n){
> > if(length(n) < 2) return(FALSE)
> > n < n[order(n)]
> > n < n  min(n)
> > step < n[2]  n[1]
> > test < seq(from = min(n), to = max(n), by = step)
> > if(length(n) == length(test) &&
> > all(n == test)){
> > return(TRUE)
> > }
> > return(FALSE)
> > }
> >
> > > .is_continous_evenly_spaced(c(1,2,3,4))
> > [1] TRUE
> > > .is_continous_evenly_spaced(c(1,3,4,5))
> > [1] FALSE
> > > .is_continous_evenly_spaced(c(1,1.1,1.2,1.3))
> > [1] FALSE
> >
> > I expect the result for 1 and 2, but not for 3. Upon Investigation
> it turns out, that n == test is TRUE for every pair, but not for the pair
> of 0.2.
> >
> > The types reported are always double, however n[2] == 0.1 reports
> FALSE as well.
> >
> > The whole problem is solved by switching from all(n == test) to
> all(as.character(n) == as.character(test)). However that is weird, isn’t it?
> >
> > Does this work as intended? Thanks for any help, advise and
> suggestions in advance.
>
> I guess this has something to do with how the sequence is built and
> the inherent error of floating point arithmetic. In fact, if you
> return test minus n, you'll get:
>
> [1] 0.000000e+00 0.000000e+00 2.220446e16 0.000000e+00
>
> and the error gets bigger when you continue the sequence; e.g., this
> is for c(1, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7):
>
> [1] 0.000000e+00 0.000000e+00 2.220446e16 2.220446e16 4.440892e16
> [6] 4.440892e16 4.440892e16 0.000000e+00
>
> So, independently of this is considered a bug or not, instead of
>
> length(n) == length(test) && all(n == test)
>
> I would use the following condition:
>
> isTRUE(all.equal(n, test))
>
> Iñaki
>
> >
> > Best regards,
> > Felix
> >
> >
> > [[alternative HTML version deleted]]
> >
> > ______________________________________________
> > [hidden email] mailing list
> > https://stat.ethz.ch/mailman/listinfo/rdevel>
>
>
> 
> Iñaki Ucar
>
> ______________________________________________
> [hidden email] mailing list
> https://stat.ethz.ch/mailman/listinfo/rdevel>
>
> ______________________________________________
> [hidden email] mailing list
> https://stat.ethz.ch/mailman/listinfo/rdevel>
[[alternative HTML version deleted]]
______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/rdevel


> On Aug 31, 2018, at 9:36 AM, Iñaki Ucar < [hidden email]> wrote:
>
> El vie., 31 ago. 2018 a las 15:10, Felix Ernst
> (< [hidden email]>) escribió:
>>
>> Dear all,
>>
>> I a bit unsure, whether this qualifies as a bug, but it is definitly a strange behaviour. That why I wanted to discuss it.
>>
>> With the following function, I want to test for evenly space numbers, starting from anywhere.
>>
>> .is_continous_evenly_spaced < function(n){
>> if(length(n) < 2) return(FALSE)
>> n < n[order(n)]
>> n < n  min(n)
>> step < n[2]  n[1]
>> test < seq(from = min(n), to = max(n), by = step)
>> if(length(n) == length(test) &&
>> all(n == test)){
>> return(TRUE)
>> }
>> return(FALSE)
>> }
>>
>>> .is_continous_evenly_spaced(c(1,2,3,4))
>> [1] TRUE
>>> .is_continous_evenly_spaced(c(1,3,4,5))
>> [1] FALSE
>>> .is_continous_evenly_spaced(c(1,1.1,1.2,1.3))
>> [1] FALSE
>>
>> I expect the result for 1 and 2, but not for 3. Upon Investigation it turns out, that n == test is TRUE for every pair, but not for the pair of 0.2.
>>
>> The types reported are always double, however n[2] == 0.1 reports FALSE as well.
>>
>> The whole problem is solved by switching from all(n == test) to all(as.character(n) == as.character(test)). However that is weird, isn’t it?
>>
>> Does this work as intended? Thanks for any help, advise and suggestions in advance.
>
> I guess this has something to do with how the sequence is built and
> the inherent error of floating point arithmetic. In fact, if you
> return test minus n, you'll get:
>
> [1] 0.000000e+00 0.000000e+00 2.220446e16 0.000000e+00
>
> and the error gets bigger when you continue the sequence; e.g., this
> is for c(1, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7):
>
> [1] 0.000000e+00 0.000000e+00 2.220446e16 2.220446e16 4.440892e16
> [6] 4.440892e16 4.440892e16 0.000000e+00
>
> So, independently of this is considered a bug or not, instead of
>
> length(n) == length(test) && all(n == test)
>
> I would use the following condition:
>
> isTRUE(all.equal(n, test))
>
> Iñaki
>
>>
>> Best regards,
>> Felix
Hi,
This is essentially FAQ 7.31:
https://cran.rproject.org/doc/FAQ/RFAQ.html#Whydoesn_0027tRthinkthesenumbersareequal_003f < https://cran.rproject.org/doc/FAQ/RFAQ.html#Whydoesn_0027tRthinkthesenumbersareequal_003f>
Review that and the references therein to gain some insights into binary representations of floating point numbers.
Rather than the more complicated code you have above, try the following:
evenlyspaced < function(x) {
gaps < diff(sort(x))
all(gaps[1] == gaps[1])
}
Note the use of ?diff:
> diff(c(1, 2, 3, 4))
[1] 1 1 1
> diff(c(1, 3, 4, 5))
[1] 2 1 1
> diff(c(1, 1.1, 1.2, 1.3))
[1] 0.1 0.1 0.1
However, in reality, due to the floating point representation issues noted above:
> print(diff(c(1, 1.1, 1.2, 1.3)), 20)
[1] 0.100000000000000088818 0.099999999999999866773
[3] 0.100000000000000088818
So the differences between the numbers are not exactly 0.1.
Using the function above, you get:
> evenlyspaced(c(1, 2, 3, 4))
[1] TRUE
> evenlyspaced(c(1, 3, 4, 5))
[1] FALSE
> evenlyspaced(c(1, 1.1, 1.2, 1.3))
[1] FALSE
As has been noted, if you want the gap comparison to be based upon some margin of error, use ?all.equal rather than the explicit equals comparison that I have in the function above. Something along the lines of:
evenlyspaced < function(x) {
gaps < diff(sort(x))
all(sapply(gaps[1], function(x) all.equal(x, gaps[1])))
}
On which case, you now get:
evenlyspaced(c(1, 1.1, 1.2, 1.3))
[1] TRUE
Regards,
Marc Schwartz
[[alternative HTML version deleted]]
______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/rdevel


Sorry for the second email: this is worth watching:
https://www.youtube.com/watch?v=3Bu7QUxzIbA&t=1sIt's Martin Maechler's talk at useR!2018. This kind of stuff should be
mandatory material for any aspiring programmer/data scientist/statistician.
Mark
Op vr 31 aug. 2018 om 16:00 schreef Mark van der Loo <
[hidden email]>:
> how about
>
> is_evenly_spaced < function(x,...) all.equal(diff(sort(x)),...)
>
> (use ellipsis to set tolerance if necessary)
>
>
> Op vr 31 aug. 2018 om 15:46 schreef Emil Bode < [hidden email]>:
>
>> Agreed that's it's rounding error, and all.equal would be the way to go.
>> I wouldn't call it a bug, it's simply part of working with floating point
>> numbers, any language has the same issue.
>>
>> And while we're at it, I think the function can be a lot shorter:
>> .is_continous_evenly_spaced < function(n){
>> length(n)>1 && isTRUE(all.equal(n[order(n)], seq(from=min(n),
>> to=max(n), length.out = length(n))))
>> }
>>
>> Cheers, Emil
>>
>> El vie., 31 ago. 2018 a las 15:10, Felix Ernst
>> (< [hidden email]>) escribió:
>> >
>> > Dear all,
>> >
>> > I a bit unsure, whether this qualifies as a bug, but it is
>> definitly a strange behaviour. That why I wanted to discuss it.
>> >
>> > With the following function, I want to test for evenly space
>> numbers, starting from anywhere.
>> >
>> > .is_continous_evenly_spaced < function(n){
>> > if(length(n) < 2) return(FALSE)
>> > n < n[order(n)]
>> > n < n  min(n)
>> > step < n[2]  n[1]
>> > test < seq(from = min(n), to = max(n), by = step)
>> > if(length(n) == length(test) &&
>> > all(n == test)){
>> > return(TRUE)
>> > }
>> > return(FALSE)
>> > }
>> >
>> > > .is_continous_evenly_spaced(c(1,2,3,4))
>> > [1] TRUE
>> > > .is_continous_evenly_spaced(c(1,3,4,5))
>> > [1] FALSE
>> > > .is_continous_evenly_spaced(c(1,1.1,1.2,1.3))
>> > [1] FALSE
>> >
>> > I expect the result for 1 and 2, but not for 3. Upon Investigation
>> it turns out, that n == test is TRUE for every pair, but not for the pair
>> of 0.2.
>> >
>> > The types reported are always double, however n[2] == 0.1 reports
>> FALSE as well.
>> >
>> > The whole problem is solved by switching from all(n == test) to
>> all(as.character(n) == as.character(test)). However that is weird, isn’t it?
>> >
>> > Does this work as intended? Thanks for any help, advise and
>> suggestions in advance.
>>
>> I guess this has something to do with how the sequence is built and
>> the inherent error of floating point arithmetic. In fact, if you
>> return test minus n, you'll get:
>>
>> [1] 0.000000e+00 0.000000e+00 2.220446e16 0.000000e+00
>>
>> and the error gets bigger when you continue the sequence; e.g., this
>> is for c(1, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7):
>>
>> [1] 0.000000e+00 0.000000e+00 2.220446e16 2.220446e16 4.440892e16
>> [6] 4.440892e16 4.440892e16 0.000000e+00
>>
>> So, independently of this is considered a bug or not, instead of
>>
>> length(n) == length(test) && all(n == test)
>>
>> I would use the following condition:
>>
>> isTRUE(all.equal(n, test))
>>
>> Iñaki
>>
>> >
>> > Best regards,
>> > Felix
>> >
>> >
>> > [[alternative HTML version deleted]]
>> >
>> > ______________________________________________
>> > [hidden email] mailing list
>> > https://stat.ethz.ch/mailman/listinfo/rdevel>>
>>
>>
>> 
>> Iñaki Ucar
>>
>> ______________________________________________
>> [hidden email] mailing list
>> https://stat.ethz.ch/mailman/listinfo/rdevel>>
>>
>> ______________________________________________
>> [hidden email] mailing list
>> https://stat.ethz.ch/mailman/listinfo/rdevel>>
>
[[alternative HTML version deleted]]
______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/rdevel


El vie., 31 ago. 2018 a las 16:00, Mark van der Loo
(< [hidden email]>) escribió:
>
> how about
>
> is_evenly_spaced < function(x,...) all.equal(diff(sort(x)),...)
This doesn't work, because
1. all.equal does *not* return FALSE. Use of isTRUE or identical(.,
TRUE) is required if you want a boolean.
2. all.equal compares two objects, not elements in a vector.
Iñaki
>
> (use ellipsis to set tolerance if necessary)
>
>
> Op vr 31 aug. 2018 om 15:46 schreef Emil Bode < [hidden email]>:
>>
>> Agreed that's it's rounding error, and all.equal would be the way to go.
>> I wouldn't call it a bug, it's simply part of working with floating point numbers, any language has the same issue.
>>
>> And while we're at it, I think the function can be a lot shorter:
>> .is_continous_evenly_spaced < function(n){
>> length(n)>1 && isTRUE(all.equal(n[order(n)], seq(from=min(n), to=max(n), length.out = length(n))))
>> }
>>
>> Cheers, Emil
>>
>> El vie., 31 ago. 2018 a las 15:10, Felix Ernst
>> (< [hidden email]>) escribió:
>> >
>> > Dear all,
>> >
>> > I a bit unsure, whether this qualifies as a bug, but it is definitly a strange behaviour. That why I wanted to discuss it.
>> >
>> > With the following function, I want to test for evenly space numbers, starting from anywhere.
>> >
>> > .is_continous_evenly_spaced < function(n){
>> > if(length(n) < 2) return(FALSE)
>> > n < n[order(n)]
>> > n < n  min(n)
>> > step < n[2]  n[1]
>> > test < seq(from = min(n), to = max(n), by = step)
>> > if(length(n) == length(test) &&
>> > all(n == test)){
>> > return(TRUE)
>> > }
>> > return(FALSE)
>> > }
>> >
>> > > .is_continous_evenly_spaced(c(1,2,3,4))
>> > [1] TRUE
>> > > .is_continous_evenly_spaced(c(1,3,4,5))
>> > [1] FALSE
>> > > .is_continous_evenly_spaced(c(1,1.1,1.2,1.3))
>> > [1] FALSE
>> >
>> > I expect the result for 1 and 2, but not for 3. Upon Investigation it turns out, that n == test is TRUE for every pair, but not for the pair of 0.2.
>> >
>> > The types reported are always double, however n[2] == 0.1 reports FALSE as well.
>> >
>> > The whole problem is solved by switching from all(n == test) to all(as.character(n) == as.character(test)). However that is weird, isn’t it?
>> >
>> > Does this work as intended? Thanks for any help, advise and suggestions in advance.
>>
>> I guess this has something to do with how the sequence is built and
>> the inherent error of floating point arithmetic. In fact, if you
>> return test minus n, you'll get:
>>
>> [1] 0.000000e+00 0.000000e+00 2.220446e16 0.000000e+00
>>
>> and the error gets bigger when you continue the sequence; e.g., this
>> is for c(1, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7):
>>
>> [1] 0.000000e+00 0.000000e+00 2.220446e16 2.220446e16 4.440892e16
>> [6] 4.440892e16 4.440892e16 0.000000e+00
>>
>> So, independently of this is considered a bug or not, instead of
>>
>> length(n) == length(test) && all(n == test)
>>
>> I would use the following condition:
>>
>> isTRUE(all.equal(n, test))
>>
>> Iñaki
>>
>> >
>> > Best regards,
>> > Felix
>> >
>> >
>> > [[alternative HTML version deleted]]
>> >
>> > ______________________________________________
>> > [hidden email] mailing list
>> > https://stat.ethz.ch/mailman/listinfo/rdevel>>
>>
>>
>> 
>> Iñaki Ucar
>>
>> ______________________________________________
>> [hidden email] mailing list
>> https://stat.ethz.ch/mailman/listinfo/rdevel>>
>>
>> ______________________________________________
>> [hidden email] mailing list
>> https://stat.ethz.ch/mailman/listinfo/rdevel
Iñaki Ucar
______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/rdevel


Ah, my bad, you're right of course.
sum(abs(diff(diff( sort(x))))) < eps
for some reasonable eps then, would do as a oneliner, or
all(abs(diff(diff(sort(x)))) < eps)
or
max(abs(diff(diff(sort(x))))) < eps
Mark
Op vr 31 aug. 2018 om 16:14 schreef Iñaki Ucar < [hidden email]>:
> El vie., 31 ago. 2018 a las 16:00, Mark van der Loo
> (< [hidden email]>) escribió:
> >
> > how about
> >
> > is_evenly_spaced < function(x,...) all.equal(diff(sort(x)),...)
>
> This doesn't work, because
>
> 1. all.equal does *not* return FALSE. Use of isTRUE or identical(.,
> TRUE) is required if you want a boolean.
> 2. all.equal compares two objects, not elements in a vector.
>
> Iñaki
>
> >
> > (use ellipsis to set tolerance if necessary)
> >
> >
> > Op vr 31 aug. 2018 om 15:46 schreef Emil Bode < [hidden email]>:
> >>
> >> Agreed that's it's rounding error, and all.equal would be the way to go.
> >> I wouldn't call it a bug, it's simply part of working with floating
> point numbers, any language has the same issue.
> >>
> >> And while we're at it, I think the function can be a lot shorter:
> >> .is_continous_evenly_spaced < function(n){
> >> length(n)>1 && isTRUE(all.equal(n[order(n)], seq(from=min(n),
> to=max(n), length.out = length(n))))
> >> }
> >>
> >> Cheers, Emil
> >>
> >> El vie., 31 ago. 2018 a las 15:10, Felix Ernst
> >> (< [hidden email]>) escribió:
> >> >
> >> > Dear all,
> >> >
> >> > I a bit unsure, whether this qualifies as a bug, but it is
> definitly a strange behaviour. That why I wanted to discuss it.
> >> >
> >> > With the following function, I want to test for evenly space
> numbers, starting from anywhere.
> >> >
> >> > .is_continous_evenly_spaced < function(n){
> >> > if(length(n) < 2) return(FALSE)
> >> > n < n[order(n)]
> >> > n < n  min(n)
> >> > step < n[2]  n[1]
> >> > test < seq(from = min(n), to = max(n), by = step)
> >> > if(length(n) == length(test) &&
> >> > all(n == test)){
> >> > return(TRUE)
> >> > }
> >> > return(FALSE)
> >> > }
> >> >
> >> > > .is_continous_evenly_spaced(c(1,2,3,4))
> >> > [1] TRUE
> >> > > .is_continous_evenly_spaced(c(1,3,4,5))
> >> > [1] FALSE
> >> > > .is_continous_evenly_spaced(c(1,1.1,1.2,1.3))
> >> > [1] FALSE
> >> >
> >> > I expect the result for 1 and 2, but not for 3. Upon
> Investigation it turns out, that n == test is TRUE for every pair, but not
> for the pair of 0.2.
> >> >
> >> > The types reported are always double, however n[2] == 0.1 reports
> FALSE as well.
> >> >
> >> > The whole problem is solved by switching from all(n == test) to
> all(as.character(n) == as.character(test)). However that is weird, isn’t it?
> >> >
> >> > Does this work as intended? Thanks for any help, advise and
> suggestions in advance.
> >>
> >> I guess this has something to do with how the sequence is built and
> >> the inherent error of floating point arithmetic. In fact, if you
> >> return test minus n, you'll get:
> >>
> >> [1] 0.000000e+00 0.000000e+00 2.220446e16 0.000000e+00
> >>
> >> and the error gets bigger when you continue the sequence; e.g., this
> >> is for c(1, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7):
> >>
> >> [1] 0.000000e+00 0.000000e+00 2.220446e16 2.220446e16 4.440892e16
> >> [6] 4.440892e16 4.440892e16 0.000000e+00
> >>
> >> So, independently of this is considered a bug or not, instead of
> >>
> >> length(n) == length(test) && all(n == test)
> >>
> >> I would use the following condition:
> >>
> >> isTRUE(all.equal(n, test))
> >>
> >> Iñaki
> >>
> >> >
> >> > Best regards,
> >> > Felix
> >> >
> >> >
> >> > [[alternative HTML version deleted]]
> >> >
> >> > ______________________________________________
> >> > [hidden email] mailing list
> >> > https://stat.ethz.ch/mailman/listinfo/rdevel> >>
> >>
> >>
> >> 
> >> Iñaki Ucar
> >>
> >> ______________________________________________
> >> [hidden email] mailing list
> >> https://stat.ethz.ch/mailman/listinfo/rdevel> >>
> >>
> >> ______________________________________________
> >> [hidden email] mailing list
> >> https://stat.ethz.ch/mailman/listinfo/rdevel>
>
>
> 
> Iñaki Ucar
>
[[alternative HTML version deleted]]
______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/rdevel


Le 31/08/2018 à 16:25, Mark van der Loo a écrit :
> Ah, my bad, you're right of course.
>
> sum(abs(diff(diff( sort(x))))) < eps
>
> for some reasonable eps then, would do as a oneliner, or
>
> all(abs(diff(diff(sort(x)))) < eps)
>
> or
>
> max(abs(diff(diff(sort(x))))) < eps
Or with only four function calls:
diff(range(diff(sort(x)))) < eps
Serguei.
>
>
> Mark
>
> Op vr 31 aug. 2018 om 16:14 schreef Iñaki Ucar < [hidden email]>:
>
>> El vie., 31 ago. 2018 a las 16:00, Mark van der Loo
>> (< [hidden email]>) escribió:
>>> how about
>>>
>>> is_evenly_spaced < function(x,...) all.equal(diff(sort(x)),...)
>> This doesn't work, because
>>
>> 1. all.equal does *not* return FALSE. Use of isTRUE or identical(.,
>> TRUE) is required if you want a boolean.
>> 2. all.equal compares two objects, not elements in a vector.
>>
>> Iñaki
>>
>>> (use ellipsis to set tolerance if necessary)
>>>
>>>
>>> Op vr 31 aug. 2018 om 15:46 schreef Emil Bode < [hidden email]>:
>>>> Agreed that's it's rounding error, and all.equal would be the way to go.
>>>> I wouldn't call it a bug, it's simply part of working with floating
>> point numbers, any language has the same issue.
>>>> And while we're at it, I think the function can be a lot shorter:
>>>> .is_continous_evenly_spaced < function(n){
>>>> length(n)>1 && isTRUE(all.equal(n[order(n)], seq(from=min(n),
>> to=max(n), length.out = length(n))))
>>>> }
>>>>
>>>> Cheers, Emil
>>>>
>>>> El vie., 31 ago. 2018 a las 15:10, Felix Ernst
>>>> (< [hidden email]>) escribió:
>>>> >
>>>> > Dear all,
>>>> >
>>>> > I a bit unsure, whether this qualifies as a bug, but it is
>> definitly a strange behaviour. That why I wanted to discuss it.
>>>> >
>>>> > With the following function, I want to test for evenly space
>> numbers, starting from anywhere.
>>>> >
>>>> > .is_continous_evenly_spaced < function(n){
>>>> > if(length(n) < 2) return(FALSE)
>>>> > n < n[order(n)]
>>>> > n < n  min(n)
>>>> > step < n[2]  n[1]
>>>> > test < seq(from = min(n), to = max(n), by = step)
>>>> > if(length(n) == length(test) &&
>>>> > all(n == test)){
>>>> > return(TRUE)
>>>> > }
>>>> > return(FALSE)
>>>> > }
>>>> >
>>>> > > .is_continous_evenly_spaced(c(1,2,3,4))
>>>> > [1] TRUE
>>>> > > .is_continous_evenly_spaced(c(1,3,4,5))
>>>> > [1] FALSE
>>>> > > .is_continous_evenly_spaced(c(1,1.1,1.2,1.3))
>>>> > [1] FALSE
>>>> >
>>>> > I expect the result for 1 and 2, but not for 3. Upon
>> Investigation it turns out, that n == test is TRUE for every pair, but not
>> for the pair of 0.2.
>>>> >
>>>> > The types reported are always double, however n[2] == 0.1 reports
>> FALSE as well.
>>>> >
>>>> > The whole problem is solved by switching from all(n == test) to
>> all(as.character(n) == as.character(test)). However that is weird, isn’t it?
>>>> >
>>>> > Does this work as intended? Thanks for any help, advise and
>> suggestions in advance.
>>>> I guess this has something to do with how the sequence is built and
>>>> the inherent error of floating point arithmetic. In fact, if you
>>>> return test minus n, you'll get:
>>>>
>>>> [1] 0.000000e+00 0.000000e+00 2.220446e16 0.000000e+00
>>>>
>>>> and the error gets bigger when you continue the sequence; e.g., this
>>>> is for c(1, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7):
>>>>
>>>> [1] 0.000000e+00 0.000000e+00 2.220446e16 2.220446e16 4.440892e16
>>>> [6] 4.440892e16 4.440892e16 0.000000e+00
>>>>
>>>> So, independently of this is considered a bug or not, instead of
>>>>
>>>> length(n) == length(test) && all(n == test)
>>>>
>>>> I would use the following condition:
>>>>
>>>> isTRUE(all.equal(n, test))
>>>>
>>>> Iñaki
>>>>
>>>> >
>>>> > Best regards,
>>>> > Felix
>>>> >
>>>> >
>>>> > [[alternative HTML version deleted]]
>>>> >
>>>> > ______________________________________________
>>>> > [hidden email] mailing list
>>>> > https://stat.ethz.ch/mailman/listinfo/rdevel>>>>
>>>>
>>>>
>>>> 
>>>> Iñaki Ucar
>>>>
>>>> ______________________________________________
>>>> [hidden email] mailing list
>>>> https://stat.ethz.ch/mailman/listinfo/rdevel>>>>
>>>>
>>>> ______________________________________________
>>>> [hidden email] mailing list
>>>> https://stat.ethz.ch/mailman/listinfo/rdevel>>
>>
>> 
>> Iñaki Ucar
>>
> [[alternative HTML version deleted]]
>
> ______________________________________________
> [hidden email] mailing list
> https://stat.ethz.ch/mailman/listinfo/rdevel>

Serguei Sokol
Ingenieur de recherche INRA
Cellule mathématiques
LISBP, INSA/INRA UMR 792, INSA/CNRS UMR 5504
135 Avenue de Rangueil
31077 Toulouse Cedex 04
tel: +33 5 62 25 01 27
email: [hidden email]
http://www.lisbp.fr______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/rdevel


El vie., 31 ago. 2018 a las 17:08, Serguei Sokol
(< [hidden email]>) escribió:
>
> Le 31/08/2018 à 16:25, Mark van der Loo a écrit :
> > Ah, my bad, you're right of course.
> >
> > sum(abs(diff(diff( sort(x))))) < eps
> >
> > for some reasonable eps then, would do as a oneliner, or
> >
> > all(abs(diff(diff(sort(x)))) < eps)
> >
> > or
> >
> > max(abs(diff(diff(sort(x))))) < eps
> Or with only four function calls:
> diff(range(diff(sort(x)))) < eps
We may have a winner... :)
Iñaki
______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/rdevel


Hello,
Watch out for operator precedence.
all.equal(0.3, 0.1*3)
#[1] TRUE
`%~~%` < function (e1, e2) all.equal(e1, e2)
0.3 %~~% 0.1*3
#Error in 0.3 %~~% 0.1 * 3 : argumento nãonumérico para operador binário
0.3 %~~% (0.1*3)
#[1] TRUE
Now with isTRUE. The problem changes a bit.
isTRUE(all.equal(0.3, 0.1*3))
#[1] TRUE
`%~~%` < function (e1, e2) isTRUE(all.equal(e1, e2))
0.3 %~~% 0.1*3
#[1] 0
0.3 %~~% (0.1*3)
#[1] TRUE
Hope this helps,
Rui Barradas
Às 08:20 de 03/09/2018, Juan Telleria Ruiz de Aguirre escreveu:
______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/rdevel


>>>>> Rui Barradas
>>>>> on Mon, 3 Sep 2018 09:58:34 +0100 writes:
> Hello, Watch out for operator precedence.
indeed! (but not only)
> all.equal(0.3, 0.1*3)
> #[1] TRUE
>
>
> `%~~%` < function (e1, e2) all.equal(e1, e2)
>
> 0.3 %~~% 0.1*3
> #Error in 0.3 %~~% 0.1 * 3 : argumento nãonumérico para operador binário
>
>
> 0.3 %~~% (0.1*3)
> #[1] TRUE
>
>
> Now with isTRUE. The problem changes a bit.
>
>
> isTRUE(all.equal(0.3, 0.1*3))
> #[1] TRUE
>
>
> `%~~%` < function (e1, e2) isTRUE(all.equal(e1, e2))
>
> 0.3 %~~% 0.1*3
> #[1] 0
>
> 0.3 %~~% (0.1*3)
> #[1] TRUE
>
> Hope this helps,
> Rui Barradas
>
> Às 08:20 de 03/09/2018, Juan Telleria Ruiz de Aguirre escreveu:
> > Maybe a new Operator could be defined for a fast and easy double
> > Comparison: `~~`
> >
> > `~~` < function (e1, e2) all.equal(e1, e2)
> >
> > And document it properly.
> >
I would still quite strongly recommend against such a
definition:
If you ask for help(all.equal)
you do see that it is a generic with a all.equal.numeric()
method which has several extra arguments
(new ones even in Rdevel) the most important one being the
numerical 'tolerance' with a default of
sqrt(.Machine$double.eps) { == 2^26 == 1.490116e08 on all current platforms}
Of course there is some arbitraryness in that choice
{{ but only *some*: the default is related to finding the minimum of
smooth function which hence is locally quadratic at a "decent"
minimum hence sqrt(.)
}}
but I find it important sometimes to increase the equality
strictness of that tolerance.
Hiding everything behind a new operator which does not allow to
take into account that there are quite a few versions of
nearequality  only partly) mirrored by the existence of
extra arguments of all.equal()  only encourages simplified
thinking about the underlying subtle issues which already too
many people don't care to know about.
(( e.g. all those people only caring for speed, but not for
accuracy and reliability ... ))
Martin Maechler
ETH Zurich and R Core
______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/rdevel

