2

I have a really weird problem.
I generated a variable through a calculation. Then I took the number and created a +0.02, -0.02 range (like, Number= 7.74, UpperRange=7.76, LowerRange=7.72).

After that I wrote a for loop, which should check if the Number is between the range. The answer must be minimum 1, because 7,74 is in the range between 7.72-7.76.
But the answer is FALSE.

But if I check if 7.73, or 7.75 is in the range, the answer is TRUE.
It will give me TRUE only with specific numbers? Why?

The code:

number= 7.74
upperRange = number + 0.02
lowerRange = number - 0.02
#
# This does not work!
# The length here is 1, but in real more than 1. For example purposes.
for(i in 1:length(number){
if(number[i] %in% seq(upperRange,lowerRange,0.01){
    print("Number is in the range")
}
else{
    print("Try again")
}
#
#
# But this works. When I change the number from 7.74 to 7.73, 7.75 or 7.76
number2 = 7.73
for(i in 1:length(number){
    if(number2[i] %in% seq(upperRange,lowerRange,0.01){
    print("Number2 is in the range")
}
else{
    print("Try again")
}
Belphegor
  • 4,456
  • 11
  • 34
  • 59
jupiter
  • 23
  • 6
  • Your code as given in your question is not reproducible. Besides mixing up `lowerRange` and `upperRange` in the call to `seq()` as pointed out by manotheshark I've found 6 (!) closing parentheses and braces are missing. – Uwe Dec 18 '16 at 22:45
  • The erratic behaviour is probably due to rounding errors when using `%in%` with double precision numbers. Unfortunately,I can't reproduce the observed effect on my machine. Please, can you try to explicitely round all involved numbers, i.e., `round(number[i], 2) %in% round(seq(lowerRange, upperRange, 0.01), 2)`? – Uwe Dec 18 '16 at 23:23

2 Answers2

2

You have the seq parameters in the wrong order. Use either of the following

seq(upperRange,lowerRange,-0.01)

seq(lowerRange,upperRange,0.01)

Although for what you're trying to accomplish, there are better methods to check if a number is between two numbers. Take a look at this answer https://stackoverflow.com/a/41201517/3242130 for examples of between, findInterval and logic comparison.

update

You'll need to load the dplyr or data.table package or explicitly reference them to use the between function

dplyr::between(number, lowerRange, upperRange)
data.table::between(number, lowerRange, upperRange)

Although if you're not using either of these packages already I'd stick with what included with base

findInterval(number, lowerRange, upperRange)==1L
number>=lowerRange & number<=upperRange
Community
  • 1
  • 1
manotheshark
  • 4,297
  • 17
  • 30
  • Thank you very much for your quick answer. The between function doesnt exists in my version of r. – jupiter Dec 18 '16 at 16:12
  • But the link you gave me, could solve my problem in a different way. Thank you very much. – jupiter Dec 18 '16 at 16:13
  • 1
    @Jupiter between is part of the `dplyr` and `data.table` packages. Answer has been updated with examples. – manotheshark Dec 18 '16 at 16:19
  • Thanks. I will try to stay with the basic methods you posted. And if the cause problems I will use the "dplyr" and "data.table" packages like you showed it. Best Regards. – jupiter Dec 18 '16 at 17:22
1

FAQ 7.31

This is a common problem when using floating point numbers.

More data; look at the values --

    > number= 7.74
    > upperRange = number + 0.02
    > lowerRange = number - 0.02
    > print(number, digits = 20)
    [1] 7.7400000000000002
    > x <- seq(lowerRange, upperRange, by = 0.01)
    > print(x, digits = 20)
    [1] 7.7200000000000006 7.7300000000000004 7.7400000000000002 7.7500000000000009 7.7599999999999998
    > 
  • That explains a lot. Thank you for showing me, what the exact problem is. – jupiter Dec 21 '16 at 19:02
  • @Jupiter this is not what was wrong with the code you posted. Floating point precision is one reason why generating a sequence to check if a number is within a range is a bad idea. – manotheshark Dec 21 '16 at 19:25