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?
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.