1

Suppose I have a vector v2 = c(50,30,10,5) and I would like to calculate the angle between v2 and itself (i.e. the angle should be 0). I use the following codes:

norm_vec = function(x) sqrt(sum(x^2))

Then I call

acos( as.numeric((v2 %*% v2) / (norm_vec(v2) * norm_vec(v2))) ) 

However, instead of getting 0, I got the following warning message:

Warning message:
In acos(as.numeric((v2 %*% v2)/(norm_vec(v2) * norm_vec(v2)))) :
  NaNs produced

I checked the value of as.numeric((v2 %*% v2) / (norm_vec(v2) * norm_vec(v2))) as it is indeed a numeric of 1. I also checked acos(1) and the result is 0. What's wrong with my codes? Thanks!

alittleboy
  • 10,616
  • 23
  • 67
  • 107

2 Answers2

3

If you set x <- as.numeric((v2 %*% v2) / (norm_vec(v2) * norm_vec(v2))), you'll "see" that x is 1. However, x == 1 will return FALSE. And x-1 will return a very tiny positive number: 2.220446e-16. acos is not defined for numbers greater than 1.

The reason is that sqrt(sum(x^2)) is slightly smaller than the true square root; the true square root is an irrational number (with infinitely many digits). In this case, since you're multiplying norm_vec(v2) by itself anyways, why not just do:

acos( as.numeric(v2 %*% v2) / sum(v2^2) )
Amit Kumar Gupta
  • 17,184
  • 7
  • 46
  • 64
  • thank you so much for your suggestions! Sorry I have to only accept one solution... I appreciate your help :) – alittleboy Sep 14 '13 at 23:06
2

See this answer: acos(1) returns NaN for some values, not others

And use pmin and pmax: acos(pmin(pmax(as.numeric(v2 %*% v2) / (norm_vec(v2) * norm_vec(v2)),-1.0), 1.0))

[1] 0

Community
  • 1
  • 1
tcash21
  • 4,880
  • 4
  • 32
  • 39