Mathematical functions
Navigate Language Fundamentals topic: ) |
![]() |
A reader has identified this page or section as an undeveloped draft or outline. You can help to develop the work, or you can ask for assistance in the project room. |
Java contains a set of mathematical functions for common operations in the class java.lang.Math. These functions include both the standard set of functions (e.g. sin, cos, tan, etc.) as well as convenience functions that mirror operations normally performed on integers.
[edit] Basic functions
abs()
returns the absolute value of a number.ceil()
returns the lowest integer that is equal to or greater than the number.floor()
returns the highest integer equal to or less than the number.rint()
andround()
round the number to the closest integer.
[edit] Exponents
pow()
returns a number to a given power.sqrt()
returns a square root.cbrt()
returns a cuberoot.log()
andlog10()
return the natural logarithm and the logarithm to base 10, respectivly.log1p()
is equivalent to log(1+x).exp()
returnse^x
.expm1()
returnse^x-1
.
[edit] Trigonometry
There are ten functions that relate to trigonometry. Three are the classic sin
, cos
and tan
functions, four are the inverses (acos
, asin
, atan
, and atan2
), and three are hyperbolic (sinh
, cosh
, and tanh
, which use a hyperbola rather than a circle for calculations.)
As with most other languages, these trigonometric functions use radians as either the parameter or return value. If you need to convert a value to or from degrees, you can use the toDegrees()
and toRadians()
functions.
[edit] Comparison functions
You can use max()
and min()
to compare two values, and return either the maximum or minimum.
[edit] Constants
E
is the base of the natural logarithms.
PI
is the ratio of a circle's circumference to its diameter.
[edit] Other methods
The code class also provides additional functions that can be used.
IEEEremainder(a, b)
, which computes the remainder ofa/b
.getExponent()
hypot(x,y)
, which returnssqrt(x^2 + y^2)
nextAfter()
nextUp()
signum()
, which returns either1
,0
, or-1
depending on the sign.scalb(x,y)
, which returnsx*2^y
ulp()
random()
, which returns a random number greater than or equal to 0 and smaller than 1
[edit] Rounding number example
Sometimes, we are not only interested in mathematically correct rounded numbers, but we want that a fixed number of significant digits are always displayed, regardless of the number used. Here is an example program that returns always the correct string. You are invited to modify it such that it does the same and is simpler!
The constant class contains repeating constants that should exist only once in the code so that to avoid inadvertant changes. (If the one constant is changed inadvertantly, it is most likely to be seen, as it used at several locations.)
![]() |
/**
* Class that comprises of common constant values. */ public class Common { /** Dash or minus constant */ public static final char DASH = '-'; /** The exponent sign in a scientific number, or the capital letter E */ public static final char EXPONENT = 'E'; /** The full stop or period */ public static final char PERIOD = '.'; /** The zero string constant used at several places */ public static final String ZERO = "0"; } // class Common |
The Maths class is like an addition to the java.lang.Math class and contains the rounding calculations.
![]() |
/**
* */ package common; /** * Class for special mathematical calculations. * ATTENTION: Should not depend on any other class except Java libraries! */ public class Maths { /** Value after which the language switches from scientific to double */ private final static double E_TO_DOUBLE = 1E-3; /** The string of zeros */ private final static String strZEROS = "000000000000000000000000000000000"; /** * Determines how many zeros are to be appended after the decimal digits. * @param SIGNIFICANTS_AFTER Requested significant digits after decimal * @param SEPARATOR Language-specific decimal separator * @param SIGNIFICANT_DIGITS Number of all significant digits * @param NUMBER Rounded number * @return Requested value */ private static byte calculateMissingSignificantZeros( final byte SIGNIFICANTS_AFTER, final char SEPARATOR, final double NUMBER) { final byte AFTER = findSignificantsAfterDecimal(SEPARATOR, NUMBER); final byte ZEROS = (byte) (SIGNIFICANTS_AFTER - ((AFTER == 0) ? 1 : AFTER)); return ((ZEROS >= 0) ? ZEROS : 0); } /** * Calculates the number of all significant digits (without the sign and * the decimal separator). * @param SIGNIFICANTS_AFTER Requested significant digits after decimal * @param SEPARATOR Language-specific decimal separator * @param NUMBER Value where the digits are to be counted * @return Number of significant digits */ private static byte findSignificantDigits(final byte SIGNIFICANTS_AFTER, final char SEPARATOR, final double NUMBER) { if (NUMBER == 0) return 0; else { String mantissa = findMantissa(SEPARATOR, new Double(NUMBER).toString()); if (NUMBER == (long)NUMBER) { mantissa = mantissa.substring(0, mantissa.length() - 1); } mantissa = RetrieveDigits(SEPARATOR, mantissa); // Find the position of the first non-zero digit: short nonZeroAt = 0; for (; (nonZeroAt < mantissa.length()) && (mantissa.charAt(nonZeroAt) == '0'); nonZeroAt++) ; return (byte)mantissa.substring(nonZeroAt).length(); } } /** * Determines the number of significant digits after the decimal separator * knowing the total number of significant digits and the number before the * decimal separator. * @param SIGNIFICANTS_BEFORE Number of significant digits before separator * @param SIGNIFICANT_DIGITS Number of all significant digits * @return Number of significant decimals after the separator */ private static byte findSignificantsAfterDecimal( final byte SIGNIFICANTS_BEFORE, final byte SIGNIFICANT_DIGITS) { final byte AFTER_DECIMAL = (byte)(SIGNIFICANT_DIGITS - SIGNIFICANTS_BEFORE); return (byte)((AFTER_DECIMAL > 0) ? AFTER_DECIMAL : 0); } /** * Finds the significant digits after the decimal separator of a mantissa. * @param SEPARATOR Language-specific decimal separator * @param NUMBER Value to be scrutinised * @return Number of significant zeros after decimal separator. */ public static byte findSignificantsAfterDecimal(final char SEPARATOR, final double NUMBER) { if (NUMBER == 0) return 1; else { String value = (new Double(NUMBER)).toString(); final short SEPARATOR_AT = (short) value.indexOf(SEPARATOR); if (SEPARATOR_AT > -1) { value = value.substring(SEPARATOR_AT + 1); } final short E_AT = (short) value.indexOf(Common.EXPONENT); if (E_AT > 0) value = value.substring(0, E_AT); Long longValue = new Long(value).longValue(); if (Math.abs(NUMBER) < 1) { return (byte) longValue.toString().length(); } else if (longValue == 0) return 0; else { value = "0." + value; return (byte) (value.length() - 2); } } } /** * Determines the number of digits before the decimal point. * @param SEPARATOR Language-specific decimal separator * @param NUMBER Value to be scrutinised * @return Number of digits before the decimal separator */ private static byte findSignificantsBeforeDecimal(final char SEPARATOR, final double NUMBER) { final String VALUE = new Double(NUMBER).toString(); // Return immediately, if result is clear: Special handling at // crossroads of floating point and exponential numbers: if ((NUMBER == 0) |
The test class checks all possibilities:
![]() |
/**
* */ package common; import java.util.Vector; /** * Test class for the common functionality * @author Saban */ public class TestCommon { /** * Test for the common functionality * @param args */ public static void main(String[] args) { // Test rounding Vector<Double> values = new Vector<Double>(); values.add(0.0); AddValue(1.4012984643248202e-45, values); AddValue(1.999999757e-5, values); AddValue(1.999999757e-4, values); AddValue(1.999999757e-3, values); AddValue(0.000640589, values); AddValue(0.3396899998188019, values); AddValue(0.34, values); AddValue(7.07, values); AddValue(118.188, values); AddValue(118.2, values); AddValue(123.405009, values); AddValue(30.76994323730469, values); AddValue(130.76994323730469, values); AddValue(540, values); AddValue(12345, values); AddValue(123456, values); AddValue(540911, values); AddValue(9.223372036854776e56, values); final byte SIGNIFICANTS = 5; for (double element : values) { System.out.println(" Maths.Round(" + SIGNIFICANTS + ", '" + Common.PERIOD + "', " + element + ") = " + Maths.roundToString(SIGNIFICANTS, Common.PERIOD, element)); } } // void main(String[] args) /** * Method that adds a negative and a positive value to values. * @param D * @param values */ private static void AddValue(final double D, Vector<Double> values) { values.add(-D); values.add(D); } } // class TestCommon |
The results of your better code should comply with the result I got:
Maths.Round(5, '.', 0.0) = 0.00000 Maths.Round(5, '.', -1.4012984643248202E-45) = -1.4012E-45 Maths.Round(5, '.', 1.4012984643248202E-45) = 1.4013E-45 Maths.Round(5, '.', -1.999999757E-5) = -1.9999E-5 Maths.Round(5, '.', 1.999999757E-5) = 2.0000E-5 Maths.Round(5, '.', -1.999999757E-4) = -1.9999E-4 Maths.Round(5, '.', 1.999999757E-4) = 2.0000E-4 Maths.Round(5, '.', -0.001999999757) = -0.0019999 Maths.Round(5, '.', 0.001999999757) = 0.0020000 Maths.Round(5, '.', -6.40589E-4) = -6.4058E-4 Maths.Round(5, '.', 6.40589E-4) = 6.4059E-4 Maths.Round(5, '.', -0.3396899998188019) = -0.33968 Maths.Round(5, '.', 0.3396899998188019) = 0.33969 Maths.Round(5, '.', -0.34) = -0.33999 Maths.Round(5, '.', 0.34) = 0.34000 Maths.Round(5, '.', -7.07) = -7.0699 Maths.Round(5, '.', 7.07) = 7.0700 Maths.Round(5, '.', -118.188) = -118.18 Maths.Round(5, '.', 118.188) = 118.19 Maths.Round(5, '.', -118.2) = -118.19 Maths.Round(5, '.', 118.2) = 118.20 Maths.Round(5, '.', -123.405009) = -123.40 Maths.Round(5, '.', 123.405009) = 123.41 Maths.Round(5, '.', -30.76994323730469) = -30.769 Maths.Round(5, '.', 30.76994323730469) = 30.770 Maths.Round(5, '.', -130.7699432373047) = -130.76 Maths.Round(5, '.', 130.7699432373047) = 130.77 Maths.Round(5, '.', -540.0) = -539.99 Maths.Round(5, '.', 540.0) = 540.00 Maths.Round(5, '.', -12345.0) = -12344 Maths.Round(5, '.', 12345.0) = 12345 Maths.Round(5, '.', -123456.0) = -123450 Maths.Round(5, '.', 123456.0) = 123460 Maths.Round(5, '.', -540911.0) = -540900 Maths.Round(5, '.', 540911.0) = 540910 Maths.Round(5, '.', -9.223372036854776E56) = -9.2233E56 Maths.Round(5, '.', 9.223372036854776E56) = 9.2234E56
If you are interested in a comparison with C#, take a look at the rounding number example there. If you are interested in a comparison with C++, you can compare this code here with the same example over there.
Notice that in the expression starting with if ((D == 0)
, I have to use OR instead of the ||
because of a bug in the source template.