From school mathematics we know that the tangent has the definition

tan(α) = sin(α) / cos(α)

and we differentiate between four quadrants based on the angle that we supply to the functions. The sign of the sin, cos and tan have the following relationship (where we neglect the exact multiples of π/2):

  Quadrant    Angle              sin   cos   tan
-------------------------------------------------
  I           0    < α < π/2      +     +     +
  II          π/2  < α < π        +     -     -
  III         π    < α < 3π/2     -     -     +
  IV          3π/2 < α < 2π       -     +     -

Given that the value of tan(α) is positive, we cannot distinguish, whether the angle was from the first or third quadrant and if it is negative, it could come from the second or fourth quadrant. So by convention, atan() returns an angle from the first or fourth quadrant (i.e. -π/2 <= atan() <= π/2), regardless of the original input to the tangent.

In order to get back the full information, we must not use the result of the division sin(α) / cos(α) but we have to look at the values of the sine and cosine separately. And this is what atan2() does. It takes both, the sin(α) and cos(α) and resolves all four quadrants by adding π to the result of atan() whenever the cosine is negative.

Remark: The atan2(y, x) function actually takes a y and a x argument, which is the projection of a vector with length v and angle α on the y- and x-axis, i.e.

y = v * sin(α)
x = v * cos(α)

which gives the relation

y/x = tan(α)

Conclusion: atan(y/x) holds back some information and one can only assume that the input came from quadrants I or IV. In contrast, atan2(y,x) gets all the data and thus can resolve the correct angle.

Answer from Mehrwolf on Stack Overflow
🌐
Coderanch
coderanch.com › t › 375015 › java › atan-atan
what is the different between atan() and atan2()? (Java in General forum at Coderanch)
November 2, 2004 - Nor will Math.atan work well if y=0, since division by 0 is not allowed. But Math.atan2 keeps the x and y arguments separated, so it can tell which quadrant the answer is in, and it can handle the case y=0.
Top answer
1 of 11
437

From school mathematics we know that the tangent has the definition

tan(α) = sin(α) / cos(α)

and we differentiate between four quadrants based on the angle that we supply to the functions. The sign of the sin, cos and tan have the following relationship (where we neglect the exact multiples of π/2):

  Quadrant    Angle              sin   cos   tan
-------------------------------------------------
  I           0    < α < π/2      +     +     +
  II          π/2  < α < π        +     -     -
  III         π    < α < 3π/2     -     -     +
  IV          3π/2 < α < 2π       -     +     -

Given that the value of tan(α) is positive, we cannot distinguish, whether the angle was from the first or third quadrant and if it is negative, it could come from the second or fourth quadrant. So by convention, atan() returns an angle from the first or fourth quadrant (i.e. -π/2 <= atan() <= π/2), regardless of the original input to the tangent.

In order to get back the full information, we must not use the result of the division sin(α) / cos(α) but we have to look at the values of the sine and cosine separately. And this is what atan2() does. It takes both, the sin(α) and cos(α) and resolves all four quadrants by adding π to the result of atan() whenever the cosine is negative.

Remark: The atan2(y, x) function actually takes a y and a x argument, which is the projection of a vector with length v and angle α on the y- and x-axis, i.e.

y = v * sin(α)
x = v * cos(α)

which gives the relation

y/x = tan(α)

Conclusion: atan(y/x) holds back some information and one can only assume that the input came from quadrants I or IV. In contrast, atan2(y,x) gets all the data and thus can resolve the correct angle.

2 of 11
176

std::atan2 allows calculating the arctangent of all four quadrants. std::atan only allows calculating from quadrants 1 and 4.

Discussions

math - Java: Tangent method - Stack Overflow
I just looked in the Math class and I know that there is: ... Why not? They are both what you're looking for. ... Yes, you do indeed want atan, or sometimes, atan2. The difference between the two is that atan will fail under some circumstances when one of the side lengths are zero. More on stackoverflow.com
🌐 stackoverflow.com
July 8, 2011
limits - Confusion about atan vs atan2 - Mathematics Stack Exchange
When I use it instead (atan2(-w*R/L, -w**2 + 1/(C*L))), I obtain: That does look like a atan plot. More on math.stackexchange.com
🌐 math.stackexchange.com
February 28, 2024
java - Guarantees concerning Math.atan2 - Stack Overflow
The documentation for Math.atan2 says The computed result must be within 2 ulps of the exact result. The fact that it says 2 ulps presumably means there are cases where the returned value is not ... More on stackoverflow.com
🌐 stackoverflow.com
Fast Atan2 [Again] - Shared Code - JVM Gaming
Background: Back at it with some Atan2 benchmarks. I found the source for my old benchmarks and wanted to run this again with some different settings. The purpose of this post is to find a faster way to do Math.atan2(y,x). To compare various methods, I setup a simple JMH benchmark and accuracy test. More on jvm-gaming.org
🌐 jvm-gaming.org
19
0
August 30, 2017
🌐
Reddit
reddit.com › r/learnjava › how does math.atan2 work?
r/learnjava on Reddit: How does Math.atan2 work?
February 24, 2021 -

I've been calculating rotation needed between two 3d points, and I'm having some slight trouble.

You can use very basic sohcahtoa to find the angle needed between the two points by making a right triangle and just doing arctan of opposite/adjacent (the two sides). Now this only works if all of the values are positive, as, for example, arctan(-5/-4) == arctan(5/4). I do remember learning something about fixing this back when I learned about trig identities in school, and how to fix it, but my friend sent me some code, and he used Math.atan2 instead of tangent.

Now his code works perfectly, and was not too different from mine, and it really made me wonder what Math.atan2 does. I searched up on the internet, and didn't understand a word of the descriptions. Can someone show me what Math.atan2 is in normal math writing?

🌐
W3Schools
w3schools.com › java › ref_math_atan2.asp
Java Math atan2() Method
System.out.println(Math.atan2(0.5, ...ath.atan2(-10, 10)); ... The atan2() method returns the angle theta in radians from the conversion of rectangular coordinates (x, y) to polar coordinates (r, theta)....
🌐
Programiz
programiz.com › java-programming › library › math › atan2
Java Math atan2()
Java Math.atan2() Java Math.copySign() ... Math sin() Java Math atan() The syntax of the atan2() method is: Math.atan2(double y, double x) Here, atan2() is a static method....
Top answer
1 of 4
8

Yes, you do indeed want atan, or sometimes, atan2. The difference between the two is that atan will fail under some circumstances when one of the side lengths are zero. While that may be unlikely for triangles, it is a possibility for some other, more general uses of atan. In addition, the atan function gives you an angle limited to the interval [-pi/2,pi/2]. So if you think about the atan function as a function of two inputs, (x,y), atan(y/x) will yield the same result as atan((-y)/(-x)). This is a serious flaw in some circumstances.

To solve these problems, the atan2 is defined such that it yields the correct result for all values of x and y, in any quadrant. One would use it as

atan2(oppositesidelength,adjacentsidelength)

to yield a consistent result.

Of course, for use in a non-degenerate triangle, the simple call to atan(opposite/adjacent) should be entirely adequate for your purposes.

2 of 4
2

Yep, you want atan, the arc tangent. This is the inverse of tangent; same thing with sin and arc sine, cosine and arc cosine, etc. These are alternative mathematical terminology for these functions' inverses.

Notice how atan returns angles from -π/2 to π/2, by the way. That's a hint that it's an inverse function (tangent takes angles and spits out ratios, arc tangent takes ratios and spits out angles). It is also important to recognize the restricted range. You won't necessarily get back your original angle, since tangents repeat every π radians (every 180°) — tan(π) = 0, but atan(0) = 0, not π.

🌐
Tutorialspoint
tutorialspoint.com › java › lang › math_atan2.htm
Java - Math atan2(double, double) Method
The Java Math atan2(double y,double x) method converts rectangular coordinates (x, y) to polar (r, theta). This method computes the phase theta by computing an arc tangent of y/x in the range of -pi to pi. Special cases ?
Find elsewhere
🌐
GeeksforGeeks
geeksforgeeks.org › java › java-lang-math-atan2-java
java.lang.Math.atan2() in Java - GeeksforGeeks
June 20, 2021 - atan2() is an inbuilt method in Java that is used to return the theta component from the polar coordinate. The atan2() method returns a numeric value between - ... \theta of a (x, y) point and the positive x-axis.
Top answer
1 of 2
3

φ = atan(m) converts the slope m of a line into the bearing angle. If the slope is zero, the angle is zero (by convention). If the slope is -∞ then the angle is -π/2 and if the slope is +∞ the angle is +π/2.

The result is limited to the 1st and 4th quadrants.

φ = atan(dy,dx) converts the direction defined by (dx,dy) into the bearing angle. If the direction points to the 2nd or 3rd quadrants (based on the signs of the arguments) then the angle result will vary between and .

Some environments define φ = atan(dx,dy) so care must be taken to get the correct order of arguments.

You must choose which function you need, as you pointed out when m=dy/dx the results are not always the same. There are cases when atan2() is preferred and cases where it is not. There are other cases you need positive angles only between 0 and π and there you use φ = acos(dx/sqrt(dx**2+dy**2)).

There is no universally proper way to do the conversion, as it depends on your assumptions related to the angle result.

Here is a graph of atan(m)

and the graph of acos(1/sqrt(1+m^2))

Both produce identical values for positive slope m, but the second one returns only the positive branch of angles for negative slope m.

and here is atan2(dx=1, dy=m)

which is identical to atan() as the direction information is lost since dx is always positive.

2 of 2
3

This is probably beating a dead horse, since the other answer explained the basic usages of $\arctan,$ $\arccos,$ and $\operatorname{atan2},$ but I don't think the other answer explained explicitly why your particular graph ended up exactly the way it did. I will focus on just that.

What you appear to be trying to do is (in effect) to plot the direction from the origin of a Cartesian plane to the point $\left(-w^2 + \frac1{C\cdot L},-\omega\cdot\frac RL\right),$ measured as an angle counterclockwise from the positive $x$-axis, for positive values of $\omega.$

Based on the results you are getting, I suppose that $C,$ $L,$ and $R$ are all positive or all negative. So when $\omega = 0,$ this point is simply $\left(\frac1{C\cdot L},0\right),$ which is a point on the positive $x$-axis and therefore has angle $0.$

As $\omega$ increases, $-w^2 + \frac1{C\cdot L}$ and $-\omega\cdot\frac RL$ both decrease. Initially the point $\left(-w^2 + \frac1{C\cdot L},-\omega\cdot\frac RL\right)$ moves downward from the $x$-axis into the fourth quadrant, but because of the $-\omega^2$ term this point starts moving left with increasing speed relative to its downward motion.

Eventually the point $\left(-w^2 + \frac1{C\cdot L},-\omega\cdot\frac RL\right)$ crosses from the fourth quadrant into the third quadrant. That is the point at which the arc tangent function "jumps" in your graph, because when $\frac yx$ is positive, $\arctan\frac yx$ always gives a first-quadrant answer, an angle between $0$ and $\frac\pi2,$ never an angle between $-\pi$ and $-\frac\pi2.$ Angles that you wanted to be reported as slightly less than $-\frac\pi2$ are reported as slightly less than $\frac\pi2$ instead.

Using $\operatorname{atan2}$ is a simple fix because when $(x,y)$ is in the third quadrant, $\operatorname{atan2}(y,x)$ gives an angle between $-\pi$ and $-\frac\pi2,$ just as you desire.

But if you want to use the older $\arctan$ function, another simple fix is to rotate the point $\left(-w^2 + \frac1{C\cdot L},-\omega\cdot\frac RL\right)$ by $\frac\pi2$ radians counterclockwise so that it goes from the first quadrant to the fourth, during which there is no "jump" in the output of $\arctan\frac yx,$ and then subtract $\frac\pi2$ to bring the angle values back to the expected interval between $-\pi$ and $0.$ You can do this by defining

$$ f(\omega) = \arctan\left(\frac{-w^2 + \frac1{C\cdot L}}{\omega\cdot \frac RL}\right) - \frac\pi2. $$

This will plot the same as your second figure. It is possible to use the old $\arctan$ function here because the angle outputs you want all lie in a single interval of width $\pi,$ just like the output of $\arctan$; you just need something like the rotation/shift described above to deal with the different positions of these equally-wide intervals on the real number line.

Top answer
1 of 2
7

Does anyone know if it is guaranteed to return the same value for equivalent pairs of int parameters?

Simply put, no. The Math documentation is the source of truth, and it provides no guarantee beyond the 2 ulp limit you reference. This is by design (as we'll see below), therefore any other source is either exposing an implementation detail or simply wrong.

Attempting to find lower bounds heuristically is impractical, since the behavior of Math is documented to be platform-specific:

Unlike some of the numeric methods of class StrictMath, all implementations of the equivalent functions of class Math are not defined to return the bit-for-bit same results. This relaxation permits better-performing implementations where strict reproducibility is not required.

Therefore even if you see tighter bounds in your tests there is no reason to believe these bounds are portable across platforms, processors, or Java versions.

However, as Math's documentation notes, StrictMath has more explicit behavior. StrictMath is documented to perform consistently across platforms, and is expected to have the same behavior as the reference implementation fdlibm. That project's readme notes:

FDLIBM is intended to provide a reasonably portable ... reference quality (below one ulp for major functions like sin,cos,exp,log) math library.

You can reference the source code for atan2 and determine precise bounds by examining its implementation; any other implementations of StrictMath.atan2() are required to give the same results as the reference implementation.

It's interesting to note that StrictMath.atan2() doesn't include the same 2 ulp comment as Math.atan2(). While it would be nice if it repeated fdlibm's "below one ulp" comment explicitly, I interpret the absence of this comment to mean StrictMath's implementation does not need to include that caveat - it will always be below one ulp.

tl;dr if you need precise results or stable results cross-platform use StrictMath. Math trades off precision for speed.

2 of 2
6

Edit: at first I thought this can be answered using "results must be semi-monotonic" requirement from the javadoc, but it actually can't be applied, so I re-wrote the answer.

Almost everything I can say is already covered by dimo414's answer. I just want to add: when using Math.atan2 on the same platform or even when using StrictMath.atan2 there is no formal guarantee (from the documentation) that atan2(y, x) == atan2(y * k, x * k). Sure, StrictMath's implementation actually uses y / x, so when y / x is precisely the same double value, the results will be equal (here I reasonably imply that function is deterministic), but keep it in mind.

Answering that part about int parameters: int holds 32 bits (actually, more like 31 bits plus one bit for sign) and can be represented by double type without any loss of precision, so no new problems there.


And the difference you described in the question (for non-overflowing long values) is caused by a loss of precision when converting long values to double, it has nothing to do with Math.atan2 itself, and it happens before the function is even called. double type can hold only 53 bits of mantissa, but in your case a * k requires 54 bits, so it is rounded to the nearest number a double can represent (b * k is okay though, it requires only 52 bits):

long a = 959786689;
long b = 363236985;
long k = 9675271;

System.out.println(a * k);
System.out.println((double) (a * k));
System.out.println((long) (double) (a * k));
System.out.println((long) (double) (a * k) == a * k);

System.out.println(b * k);
System.out.println((double) (b * k));
System.out.println((long) (double) (b * k));
System.out.println((long) (double) (b * k) == b * k);

Output:

9286196318267719
9.28619631826772E15
9286196318267720
false
3514416267097935
3.514416267097935E15
3514416267097935
true

And to address the example from the comment:

We have double a = 1.02551177480084, b = 1.12312341356234, k = 5;. In this case none of a, b, a * k, b * k can be represented as double without loss of precision. I'll use BigDecimal to demonstrate it, because it can show the true (not rounded) value of double:

double a = 1.02551177480084;
System.out.println("a is            " + new BigDecimal(a));
System.out.println("a * 5 is        " + new BigDecimal(a * 5));
System.out.println("a * 5 should be " + new BigDecimal(a).multiply(new BigDecimal("5")));

outputs

a is            1.0255117748008399924941613789997063577175140380859375
a * 5 is        5.12755887400420018451541182002983987331390380859375   // precision loss here
a * 5 should be 5.1275588740041999624708068949985317885875701904296875

and the difference can be clearly seen (same can be done with b instead of a).

There is a more simple test (since atan2() essentially uses a/b):

double a = 1.02551177480084, b = 1.12312341356234, k = 5;
System.out.println(a / b == (a * k) / (b * k));

outputs

false
🌐
Wikipedia
en.wikipedia.org › wiki › Atan2
atan2 - Wikipedia
January 20, 2026 - The C function atan2, and most other computer implementations, are designed to reduce the effort of transforming cartesian to polar coordinates and so always define atan2(0, 0). On implementations without signed zero, or when given positive ...
🌐
DEV Community
dev.to › satyam_gupta_0d1ff2152dcc › master-java-atan2-your-guide-to-angles-not-just-math-1n2o
Master Java atan2(): Your Guide to Angles, Not Just Math - DEV Community
November 28, 2025 - So, if you have a point in, say, ... blind to the correct quadrant. atan2(), on the other hand, knows the individual x and y values, so it always places the angle in the correct quadrant....
🌐
Tutorial Gateway
tutorialgateway.org › java-atan2-function
Java atan2 Function
November 28, 2024 - The Math.atan2 Function in this Programming returns the angle (in radius) from the X-Axis to the specified point (y, x). In this Java program, We find the same with positive and negative values and display the output.
🌐
JVM Gaming
jvm-gaming.org › shared code
Fast Atan2 [Again] - Shared Code - JVM Gaming
August 30, 2017 - Background: Back at it with some Atan2 benchmarks. I found the source for my old benchmarks and wanted to run this again with some different settings. The purpose of this post is to find a faster way to do Math.atan2(y,x). To compare various methods, I setup a simple JMH benchmark and accuracy test.
🌐
JVM Gaming
jvm-gaming.org › shared code
Extremely Fast atan2 - Shared Code - JVM Gaming
July 25, 2015 - Hello, I’ve just been looking around for a faster way to do Math.atan2(y,x) and I came across a number of methods. To compare them, I setup a simple JMH benchmark and accuracy test. Criticisms and new atan2 submissions are appreciated. Recommended implementation with lookup table: Icecore’s Recommended implementation without lookup table: Kappa’s Relevant data Current results: apache_atan2 : Average Error 0.00000 / Largest Error 0.00000 - Performance 367.945 ns/op default_a...
🌐
Dirask
dirask.com › posts › Java-Math-atan2-method-example-1RvQ81
Java - Math.atan2() method example
The Math.atan2() function returns the angle in radians in the range -Math.PI/2 to +Math.PI/2 between the positive x-axis and the ray to the point (x, y) ≠ (0, 0) · atan2() method has been visualized on below image:
🌐
Tutorialspoint
tutorialspoint.com › home › java › java atan2 method
Java atan2 Method
June 24, 2024 - Learn how to use the atan2 method in Java for calculating the angle whose tangent is the quotient of two specified numbers.
🌐
Medium
medium.com › @sddkal › difference-between-atan-and-atan2-b2d5df4d8b30
Difference Between Atan and Atan2 | by Sıddık Açıl | Medium
May 5, 2018 - Difference Between Atan and Atan2 In this article, I am going to talk about an interesting dichotomy that occurs in libraries on mathematics. In any math library, there exists two different kinds of …