2

I am trying to check if values are present in a sequence of numbers using the %in% operator in R. The sequence is generated using the seq() function with a step of 0.01, ranging from 0.50 to 1.10.

Here are the different inputs I tried:

.55 %in% seq(.50, 1.1, by = .01)
.57 %in% seq(.50, 1.1, by = .01)

".55" %in% seq(.50, 1.1, by = .01)
".57" %in% seq(.50, 1.1, by = .01)

"0.55" %in% seq(.50, 1.1, by = .01)
"0.57" %in% seq(.50, 1.1, by = .01)

0.55 %in% seq(.50, 1.1, by = .01)
0.57 %in% seq(.50, 1.1, by = .01)

However, the outputs for these inputs are confusing and unexpected:

[1] TRUE
[1] FALSE

[1] FALSE
[1] FALSE

[1] TRUE
[1] TRUE

[1] TRUE
[1] FALSE
  1. Does anyone know why .55 is recognized in the sequence, but .57 isn't?

  2. How come when we add a leading zero and put quotes it returns TRUE?

  3. How come quotes without a leading zero returns FALSE?

  • @AllanCameron, please post these as answers ... – Ben Bolker Apr 19 '23 at 20:48
  • 2
    Seems fair (although I guess finding a single dupe-target could be challenging). Frustrating when answering is less effort than finding the appropriate dupe-target ... – Ben Bolker Apr 19 '23 at 20:50
  • @BenBolker you're right - there's no single exact duplicate that I can find. I'll post an answer and if anyone wants to close as a duplicate I won't mind. – Allan Cameron Apr 19 '23 at 21:11

1 Answers1

3

The answer to your first question is that it is not safe to compare floating point numbers for exact equality - see "Why are these numbers not equal?"

The answer to your second question is that the numbers in seq are converted to characters for the comparison, and the character output of the sequence is what is shown in the console if we do:

as.character(seq(.50, 1.1, by = .01))
#>  [1] "0.5"  "0.51" "0.52" "0.53" "0.54" "0.55" "0.56" "0.57" "0.58" "0.59" "0.6" 
#> [12] "0.61" "0.62" "0.63" "0.64" "0.65" "0.66" "0.67" "0.68" "0.69" "0.7"  "0.71"
#> [23] "0.72" "0.73" "0.74" "0.75" "0.76" "0.77" "0.78" "0.79" "0.8"  "0.81" "0.82"
#> [34] "0.83" "0.84" "0.85" "0.86" "0.87" "0.88" "0.89" "0.9"  "0.91" "0.92" "0.93"
#> [45] "0.94" "0.95" "0.96" "0.97" "0.98" "0.99" "1"    "1.01" "1.02" "1.03" "1.04"
#> [56] "1.05" "1.06" "1.07" "1.08" "1.09" "1.1" 

Note that the strings "0.55" and "0.57" are both present here.

The answer to your third question is simply that the strings ".55" and ".57" do not appear in the above result.

Allan Cameron
  • 147,086
  • 7
  • 49
  • 87