0

My goal is to check if a given number is in a cut type interval or range like this: "[1.86e+03,2.43e+03]". I get the interval as a string. I'm having trouble with the higher end of the interval for some reason and can't see what I'm doing wrong, the lower seems to work fine and I haven't included it in the code below.

Here's a part of the code that doesn't seem to work:

library(readr)

IsNumLess <- function(num, interval) {

  intervalL <- unlist(strsplit(interval, ",")) #split on comma
  lastSt <- intervalL[2]      #get the whole second part
  lastNum <- parse_number(lastSt)  #get just the number, without ) or ]

if (endsWith(lastSt, ']')) #up to and including
  {
    if (!(num <= lastNum))
   {
    print(num)
    print(lastNum)
    print(num <= lastNum)  #this and line below should return the same value
    print(2430 <= 2430)
    print("f3")
    return(FALSE)
    }
  }
else # ) - up to but not including
  {
    if (!(num < lastNum))
    {
      print("f4")
      return(FALSE)
    }
  }
  return(TRUE)
}

If I run this IsNumLess(2430, "[1.86e+03,2.43e+03]") it comes back as FALSE, and it should be TRUE as 2430 <= 2.43e+03...

> IsNumLessMin(2430, "[1.86e+03,2.43e+03]")
[1] 2430
[1] 2430
[1] FALSE
[1] TRUE
[1] "f3"
[1] FALSE

Edit: Thank you G5W, the duplicate question link got me to where I needed.... This line worked in the second 'if':

if (!(num < lastNum | isTRUE(all.equal(num, lastNum))))
Oleg
  • 303
  • 2
  • 14
  • Try, `2340 == 2.43e+03` This is roundoff error.Also, try `options(digits=20); 2.43` – G5W Sep 06 '19 at 18:04
  • It should never get to the else with "...2.43e+03]" being up to and including... and return the TRUE at the end. – Oleg Sep 06 '19 at 18:06
  • Not the else part, It is executing if. But 2.43e3 > 2430 :-) – G5W Sep 06 '19 at 18:08
  • Change the function to accept a tolerance (i.e. `function(num, interval, tolerance)`, then change the condition inside the function to `if (!(abs(num - lastNum) < (tolerance)))`, then it works. (don't forget to also change the second condition). Call the function with `IsNumLess(2430, "[1.86e+03,2.43e+03]", 0.00001)` – stevec Sep 06 '19 at 18:16

1 Answers1

0

This is a problem with the accuracy of representing decimals in a computer. See here for an in depth discussion.

If you run:

sprintf("%.54f",num)  
sprintf("%.54f",lastNum)

You will see that the num != lastNum .

An easy fix in your code is to replace print(num <= lastNum) with print(num < lastNum | all.equal(num, lastNum)).

Lief Esbenshade
  • 793
  • 4
  • 13
  • My goal is to see if a number is in the range, the print statements are just for debugging... I'd like to get to the TRUE. – Oleg Sep 06 '19 at 18:11
  • 1
    if (!(num < lastNum | isTRUE(all.equal(num, lastNum)))) I needed the isTRUE, but this was it... from the docs here: https://www.rdocumentation.org/packages/base/versions/3.6.1/topics/all.equal – Oleg Sep 06 '19 at 18:34