# compairing doubles

14 messages
Open this post in threaded view
|

## compairing doubles

 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/r-devel
Open this post in threaded view
|

## Re: compairing doubles

 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.220446e-16 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.220446e-16 2.220446e-16 4.440892e-16 [6] 4.440892e-16 4.440892e-16 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/r-devel-- Iñaki Ucar ______________________________________________ [hidden email] mailing list https://stat.ethz.ch/mailman/listinfo/r-devel
Open this post in threaded view
|

## Re: compairing doubles

 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.220446e-16 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.220446e-16 2.220446e-16 4.440892e-16     [6] 4.440892e-16 4.440892e-16 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/r-devel                --     Iñaki Ucar         ______________________________________________     [hidden email] mailing list     https://stat.ethz.ch/mailman/listinfo/r-devel    ______________________________________________ [hidden email] mailing list https://stat.ethz.ch/mailman/listinfo/r-devel
Open this post in threaded view
|

## Re: compairing doubles

 In reply to this post by Iñaki Ucar 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.220446e-16 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.220446e-16 2.220446e-16 4.440892e-16 > [6] 4.440892e-16 4.440892e-16 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/r-devel> > > > -- > Iñaki Ucar -- Iñaki Ucar ______________________________________________ [hidden email] mailing list https://stat.ethz.ch/mailman/listinfo/r-devel
Open this post in threaded view
|

## Re: compairing doubles

 In reply to this post by Emil 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.220446e-16 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.220446e-16 2.220446e-16 4.440892e-16 >     [6] 4.440892e-16 4.440892e-16 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/r-devel> > > >     -- >     Iñaki Ucar > >     ______________________________________________ >     [hidden email] mailing list >     https://stat.ethz.ch/mailman/listinfo/r-devel> > > ______________________________________________ > [hidden email] mailing list > https://stat.ethz.ch/mailman/listinfo/r-devel>         [[alternative HTML version deleted]] ______________________________________________ [hidden email] mailing list https://stat.ethz.ch/mailman/listinfo/r-devel
Open this post in threaded view
|

## Re: compairing doubles

 In reply to this post by Iñaki Ucar > 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.220446e-16 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.220446e-16 2.220446e-16 4.440892e-16 > [6] 4.440892e-16 4.440892e-16 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.r-project.org/doc/FAQ/R-FAQ.html#Why-doesn_0027t-R-think-these-numbers-are-equal_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/r-devel
Open this post in threaded view
|

## Re: compairing doubles

 In reply to this post by Mark van der Loo Sorry for the second e-mail: 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.220446e-16 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.220446e-16 2.220446e-16 4.440892e-16 >>     [6] 4.440892e-16 4.440892e-16 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/r-devel>> >> >> >>     -- >>     Iñaki Ucar >> >>     ______________________________________________ >>     [hidden email] mailing list >>     https://stat.ethz.ch/mailman/listinfo/r-devel>> >> >> ______________________________________________ >> [hidden email] mailing list >> https://stat.ethz.ch/mailman/listinfo/r-devel>> >         [[alternative HTML version deleted]] ______________________________________________ [hidden email] mailing list https://stat.ethz.ch/mailman/listinfo/r-devel
Open this post in threaded view
|

## Re: compairing doubles

 In reply to this post by Mark van der Loo 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.220446e-16 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.220446e-16 2.220446e-16 4.440892e-16 >>     [6] 4.440892e-16 4.440892e-16 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/r-devel>> >> >> >>     -- >>     Iñaki Ucar >> >>     ______________________________________________ >>     [hidden email] mailing list >>     https://stat.ethz.ch/mailman/listinfo/r-devel>> >> >> ______________________________________________ >> [hidden email] mailing list >> https://stat.ethz.ch/mailman/listinfo/r-devel-- Iñaki Ucar ______________________________________________ [hidden email] mailing list https://stat.ethz.ch/mailman/listinfo/r-devel
Open this post in threaded view
|

## Re: compairing doubles

 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.220446e-16 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.220446e-16 2.220446e-16 4.440892e-16 > >>     [6] 4.440892e-16 4.440892e-16 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/r-devel> >> > >> > >> > >>     -- > >>     Iñaki Ucar > >> > >>     ______________________________________________ > >>     [hidden email] mailing list > >>     https://stat.ethz.ch/mailman/listinfo/r-devel> >> > >> > >> ______________________________________________ > >> [hidden email] mailing list > >> https://stat.ethz.ch/mailman/listinfo/r-devel> > > > -- > Iñaki Ucar >         [[alternative HTML version deleted]] ______________________________________________ [hidden email] mailing list https://stat.ethz.ch/mailman/listinfo/r-devel
Open this post in threaded view
|

## Re: compairing doubles

 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.220446e-16 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.220446e-16 2.220446e-16 4.440892e-16 >>>>      [6] 4.440892e-16 4.440892e-16 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/r-devel>>>> >>>> >>>> >>>>      -- >>>>      Iñaki Ucar >>>> >>>>      ______________________________________________ >>>>      [hidden email] mailing list >>>>      https://stat.ethz.ch/mailman/listinfo/r-devel>>>> >>>> >>>> ______________________________________________ >>>> [hidden email] mailing list >>>> https://stat.ethz.ch/mailman/listinfo/r-devel>> >> >> -- >> Iñaki Ucar >> > [[alternative HTML version deleted]] > > ______________________________________________ > [hidden email] mailing list > https://stat.ethz.ch/mailman/listinfo/r-devel> -- 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/r-devel
Open this post in threaded view
|

## Re: compairing doubles

 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/r-devel
Open this post in threaded view
|

## Re: compairing doubles

 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. ______________________________________________ [hidden email] mailing list https://stat.ethz.ch/mailman/listinfo/r-devel