Czyli działa (w miarę) poprawnie. Powinno być +inf, jest jakaś bardzo duża liczba.
Po pierwsze - Math.PI to nie jest liczba PI. To jest pewne przybliżenie liczby PI (której dokładnie nie da się zapisać, bo jest to liczba niewymierna). Mamy więc pierwsze źródło błędów numerycznych - operowanie na wartościach przybliżonych.
Wyliczając kąt w radianach nie wyliczymy dokładnie tego PI, PI/2 (innych kątów też nie), lecz jedynie ich pewne przybliżenia.
W zależności od tego, jakie to będą przybliżenia, otrzymamy mniej lub bardziej dokładne wyniki.
Nie wspominając o tym, jak ten tangens jest zaimplementowany. Gdzieś znalazłem informację, że jest to sin(x) / cos(x) - ale jak są zaimplementowane te sinusy i cosinusy? To są jakieś algorytmy numeryczne, a więc wyniki będą przybliżone (czasami lepiej, czasami gorzej) i obarczone błędami numerycznymi.
No i potem takie "kwiatki" wychodzą.
Zresztą nie trzeba funkcji trygonometrycznych, żeby doświadczyć problemów numerycznych: proponuję wpisać w JS a = 0.1, a potem sprawdzić wynik a + a + a (u mnie np. wcale nie wychodzi 0.3; co ciekawe, przy dalszym dodawaniu są poprawne wyniki, ale już przy ośmiu składnikach też nie mam 0.8). Można też popróbować z a = 0.01, a = 0.001... Ciekawskim polecam sprawdzić a = 0.125 i zastanowić się, dlaczego dla tej interesującej wartości akurat wszystko liczone jest poprawnie.
Generalnie, operując na liczbach zmiennoprzecinkowych, należy przyjąć pewną dokładność. Tzn. nie porównujemy wartości zmiennych do stałych, lecz sprawdzamy, czy wartość bezwzględna różnicy jest odpowiednio mała: if ( Math.abs(a - 2) < EPSILON ) ...
Podobnie można postąpić z tymi kątami. Nie wyliczymy dokładnie pewnych wartości (np. tych 45, 90, czy 180 stopni) - to może warto napisać własną funkcję, która dla tych specyficznych wartości (z pewną dokładnością) zwróci poprawny wynik?