Order of operations when using arithmetic and logical operators

I think I'm going slightly mad here. If FALSE * FALSE returns zero and !TRUE is returns FALSE, why does !TRUE * !TRUE return TRUE?

# All should return 0 or FALSE

FALSE * FALSE
#> [1] 0

!TRUE
#> [1] FALSE

!TRUE * !TRUE
#> [1] TRUE
# wut

(!TRUE) * (!TRUE)
#> [1] 0

Created on 2019-07-03 by the reprex package (v0.3.0)

After further investigation, it seems like this is an order of operations issue. If I use the logical & operator instead of *, I get the right answer. Does anyone know how the order of operations works when mixing arithmetic and logical operators?

# All should return FALSE

FALSE & FALSE
#> [1] FALSE

!TRUE
#> [1] FALSE

!TRUE & !TRUE
#> [1] FALSE
# better

(!TRUE) & (!TRUE)
#> [1] FALSE

Created on 2019-07-03 by the reprex package (v0.3.0)

Seems like one should try to always stay in either arithmetic world if possible. What do you all think?

Welp, it's documented here. I don't think this is a bug. Just really surprised me!

You can see what R thinks about with lobstr:

library(lobstr)
ast(!TRUE * !TRUE)
#> █─`!` 
#> └─█─`*` 
#>   ├─TRUE 
#>   └─█─`!` 
#>     └─TRUE

Created on 2019-07-03 by the reprex package (v0.3.0)

You can then go through step-by-step to see the result.

But in general, using logicals in such a manner is always a bit too clever for me for specifically reasons such as you've found.

Thanks, @mishabalyasin! This is super helpful. I've heard of lobstr, but haven't tried it yet! This is good use case for it.

1 Like

This topic was automatically closed 21 days after the last reply. New replies are no longer allowed.