Search code examples
rcomplex-numberseigenvalue

Different ways to check whether an eigenvalue equals a real number?


I have the following matrix

M <- structure(c(0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 
0, 0, 1, 0, 0, 0, 1, 0), .Dim = c(5L, 5L))

I want to find the eigenvalues that are exactly 1. I thought this would work:

Re(eigen(M)$values) == 1 & Im(eigen(M)$values) == 0

but Re(eigen(M)$values) == 1 doesn't think the 5th eigenvalues equals 1, even though it does. What am I missing?

EDIT: As soon as it's pointed out as a floating point problem, I investigate a bit more and find out about several solution, including using abs(value) < tol, all.equal, and signif. Could an answer discuss these options?


Solution

  • In R, the usual way to deal with floating-point numbers in the case of comparisons like == is to use the function all.equal().

    You may want to try:

    sapply(1:nrow(M), function(x) identical(all.equal(eigen(M)$values[x],1+0i),TRUE))
    [1] FALSE FALSE  TRUE FALSE  TRUE
    

    There are often workarounds that lead to the same result (round, signif...), but using all.equal() is preferable since it is a function that is designed to handle comparisons of floating point numbers, without the need to tweak accuracy thresholds or to specify the number of significant digits.

    As stated in ?Comparison:

    For numerical and complex values, remember == and != do not allow for the finite representation of fractions, nor for rounding error. Using all.equal with identical is almost always preferable.