Mathematical functions

From Wikibooks, open books for an open world
Jump to: navigation, search

Basic Arithmetic Java Programming
Mathematical functions
Large numbers
Navigate Language Fundamentals topic: v  d  e )

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() and round() 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() and log10() return the natural logarithm and the logarithm to base 10, respectivly. log1p() is equivalent to log(1+x).
  • exp() returns e^x. expm1() returns e^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 of a/b.
  • getExponent()
  • hypot(x,y), which returns sqrt(x^2 + y^2)
  • nextAfter()
  • nextUp()
  • signum(), which returns either 1, 0, or -1 depending on the sign.
  • scalb(x,y), which returns x*2^y
  • ulp()
  • random()

[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.)

Computer code
/**
 * 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.

Computer code
/**
 *
 */

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:

Computer code
/**
 *
 */

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.


Basic Arithmetic Java Programming
Mathematical functions
Large numbers
Personal tools
Namespaces

Variants
Actions
Navigation
Community
Toolbox
Sister projects
Print/export