Mathematical operations in Java: java.util.Math (ctd)
This page continues from the previous page on information
and performance of methods provided by the java.util.Math class. Please see
that page in particular for information about interpreting the timing information given below.
Math.log(): natural logarithm
The method Math.log() computes the natural logarithm, or in
other words, the opposite of Math.exp(), and often written either
ln(x) or log10(x).
Like ex, calculating natural logarithms crops up in
various mathematical applications.
Hotspot on Intel architectures makes use of the FYL2X instruction
which calculates a base 2 logarithm, and the equivalence ln(x) ≡ log2 * log2(x). With this implementation, calling Math.log() appears to
take in the order of 50 clock cycles on our test i7 machine, or about
25-50 times slower than a floating point addition depending on circumstances.
Math.pow(): calculating arbitrary powers
The Math.pow() method can be used to calculate arbitrary powers.
Specifically, calling Math.pow(x, y) calculates xy,
where both x and y can be any arbitrary double and the result
will be the nearest double representation possible to the actual
answer.
It should be noted that Math.pow() is potentially very slow
compared to many other operations. On our test system, it takes something in
the order of 600 clock cycles in the worst case.
However, the algorithm used does
provide for a a special "fast case" where y is a power of 2 where
it takes in the order of 30 clock cycles.
Math.sin(), Math.cos() and Math.tan(): calculating sines, cosines and tangents
These functions calculate the key trigonometric functions sine,
cosine and tangent which define the relationship between the angle of a right-angled triangle
and the ratios of the lengths pairs of its sides. These functions crop up in a variety
of applications, from the simple drawing of geometrical shapes to more complex operations
such as the analysis of waveforms. They each take their input value in radians,
where a full circle or 360 degrees is equivalent to 2*pi radians. (In a program,
you can get the double value of PI using the constant Math.PI.)
The sine, cosine and tangent functions are all repeating functions, whereby the
"core" behaviour of the function with input values between 0 and pi/2 is effectively repeated
(with sign changes) over other ranges of input values. Because less "juggling" is
required to accommodate this repetition, Java's sin(), cos()
and tan() functions have "fast cases" for input values between -pi/2 and pi/2. Approximate
number of clock cycles (i.e. relative to the "best case" for a floating point addition
on many processors) are approximately as follows:
Function | Input range | Timing (reative to floating point addition) |
Math.sin() Math.cos() | -pi/2 - pi/2 | ~ 65 |
< -pi/2 or > pi/2 | ~ 120 |
Math.tan() | -pi/2 - pi/2 | ~ 80 |
< -pi/2 or > pi/2 | ~ 200 |
Notice that tan() is functionally equivalent to sin()/cos() but that
it is faster (and marginally more accurate) to use the tan() function because a different
method of calculation is actually used.
If you enjoy this Java programming article, please share with friends and colleagues. Follow the author on Twitter for the latest news and rants.
Editorial page content written by Neil Coffey. Copyright © Javamex UK 2021. All rights reserved.