Java Math Class: Essential Methods with Examples

Introduction Square roots, powers, rounding, absolute values, random numbers - most programs need a few mathematical operations, and Java provides them in the java.lang.Math class. This tutorial explains the essential methods of the Java Math class with examples. We will start with what the Math class is and its two constants. We will then look at the basic methods - abs(), max(), min() - and at powers and roots. Next we will compare the four ways of rounding, which are a common source of bugs. We will then generate random numbers, and use the exact methods which detect overflow. Lastly, we will go through the trigonometric and logarithmic methods, and the pitfalls to watch for.

(Note - This tutorial builds on Java Primitive Data TypesClick to read tutorial: Java Primitive Data Types and Their Ranges with Examples and Type Conversion and CastingClick to read tutorial: Type Conversion and Casting in Java with Examples.) What is the Math class? java.lang.Math is a class of static methods and constants for numeric calculations. It is in java.lang, so it needs no import. You never create a Math object - its constructor is private - you call its methods on the class itself, such as Math.sqrt(16). (See static vs instance methodsClick to read tutorial: Static vs Instance Methods in Java.)

It has two constants -
  • Math.PI - the ratio of a circle's circumference to its diameter, 3.141592653589793.
  • Math.E - the base of natural logarithms, 2.718281828459045.
Most methods take and return double values. Several, such as abs(), max() and min(), are overloadedClick to read tutorial: Method Overloading in Java with Examples for int, long, float and double, and return the same type they are given. Basic methods - abs(), max(), min() and signum()
abs(), max(), min(), signum() and the constants
//BasicMath.java
public class BasicMath {
  public static void main(String[] args) {
    System.out.println("Math.abs(-42)       = " + Math.abs(-42));
    System.out.println("Math.abs(-3.5)      = " + Math.abs(-3.5));
    System.out.println("Math.max(17, 42)    = " + Math.max(17, 42));
    System.out.println("Math.min(2.5, -1.0) = " + Math.min(2.5, -1.0));
    System.out.println("Math.signum(-8.0)   = " + Math.signum(-8.0));

    int a = 7, b = 19, c = 11;
    System.out.println("Largest of three    = " + Math.max(a, Math.max(b, c)));

    double radius = 2.5;
    System.out.println("Circle area         = " + Math.PI * radius * radius);
    System.out.println("Math.E              = " + Math.E);
  }
}
 OUTPUT of the above code
Math.abs(-42)       = 42
Math.abs(-3.5)      = 3.5
Math.max(17, 42)    = 42
Math.min(2.5, -1.0) = -1.0
Math.signum(-8.0)   = -1.0
Largest of three    = 19
Circle area         = 19.634954084936208
Math.E              = 2.718281828459045
Explanation of the code
  • abs() returns the value without its sign, and keeps the argument's type - Math.abs(-42) is the int 42.
  • max() and min() take exactly two values. To find the largest of three, nest the calls.
  • signum() returns -1.0, 0.0 or 1.0, depending on the sign of its argument.
Powers and roots - pow(), sqrt(), cbrt() and hypot()
Powers and roots
//PowersRoots.java
public class PowersRoots {
  public static void main(String[] args) {
    System.out.println("Math.pow(2, 10)    = " + Math.pow(2, 10));
    System.out.println("Math.pow(9, 0.5)   = " + Math.pow(9, 0.5));
    System.out.println("Math.pow(2, -2)    = " + Math.pow(2, -2));
    System.out.println("Math.sqrt(144)     = " + Math.sqrt(144));
    System.out.println("Math.cbrt(27)      = " + Math.cbrt(27));
    System.out.println("Math.hypot(3, 4)   = " + Math.hypot(3, 4));
    System.out.println("Math.sqrt(-1)      = " + Math.sqrt(-1));
    System.out.println("2 ^ 10 (XOR!)      = " + (2 ^ 10));

    double principal = 1000, rate = 0.05;
    int years = 10;
    double amount = principal * Math.pow(1 + rate, years);
    System.out.printf("1000 at 5%% for 10 years = %.2f%n", amount);

    int asInt = (int) Math.pow(2, 10);
    System.out.println("(int) Math.pow(2, 10) = " + asInt);
  }
}
 OUTPUT of the above code
Math.pow(2, 10)    = 1024.0
Math.pow(9, 0.5)   = 3.0
Math.pow(2, -2)    = 0.25
Math.sqrt(144)     = 12.0
Math.cbrt(27)      = 3.0
Math.hypot(3, 4)   = 5.0
Math.sqrt(-1)      = NaN
2 ^ 10 (XOR!)      = 8
1000 at 5% for 10 years = 1628.89
(int) Math.pow(2, 10) = 1024
Explanation of the code
  • pow() always returns a double, so Math.pow(2, 10) is 1024.0. Cast the result when you need an integer.
  • A power of 0.5 is a square root, and a negative power is a reciprocal - 2-2 is 0.25.
  • The square root of a negative number is NaN (Not a Number), not an exception.
  • 2 ^ 10 is 8, not 1024 - a classic mistake for programmers coming from languages where ^ means "power".
  • For powers of two in integer code, a shift is exact and faster: 1 << 10 is 1024.
Rounding - round(), floor(), ceil() and rint() Java has four rounding methods, and they treat halves and negative numbers differently -
  • floor(x) - rounds down, towards negative infinity. Returns a double.
  • ceil(x) - rounds up, towards positive infinity. Returns a double.
  • round(x) - rounds to the nearest whole number, with halves rounded up (towards positive infinity). Returns a long for a double argument, and an int for a float.
  • rint(x) - rounds to the nearest whole number, with halves rounded to the nearest even number. Returns a double.
Comparing the rounding methods
//Rounding.java
public class Rounding {
  public static void main(String[] args) {
    double[] values = {2.4, 2.5, 2.6, 3.5, -2.5, -2.6};
    System.out.println("value   floor   ceil   round   rint   (int) cast");
    for (double v : values) {
      System.out.printf("%5.1f  %6.1f  %5.1f  %5d  %6.1f  %6d%n",
          v, Math.floor(v), Math.ceil(v), Math.round(v), Math.rint(v), (int) v);
    }

    double price = 19.98765;
    System.out.println("Two decimals (display): " + String.format("%.2f", price));
    System.out.println("Two decimals (value)  : " + Math.round(price * 100) / 100.0);

    int items = 23, perBox = 5;
    System.out.println("Boxes needed: " + (int) Math.ceil((double) items / perBox));
    System.out.println("Boxes needed (integer): " + Math.ceilDiv(items, perBox));
  }
}
 OUTPUT of the above code
value   floor   ceil   round   rint   (int) cast
  2.4     2.0    3.0      2     2.0       2
  2.5     2.0    3.0      3     2.0       2
  2.6     2.0    3.0      3     3.0       2
  3.5     3.0    4.0      4     4.0       3
 -2.5    -3.0   -2.0     -2    -2.0      -2
 -2.6    -3.0   -2.0     -3    -3.0      -2
Two decimals (display): 19.99
Two decimals (value)  : 19.99
Boxes needed: 5
Boxes needed (integer): 5
Explanation of the code
  • Math.round(-2.5) is -2, not -3, because halves go up towards positive infinity. rint() sends halves to the even neighbour, so 2.5 becomes 2.0 and 3.5 becomes 4.0 - this banker's rounding avoids bias when many values are rounded.
  • A (int) cast is not rounding at all - it just drops the fractional part, towards zero.
  • To display a value with two decimals, use String.format(). Rounding the value itself with Math.round(x * 100) / 100.0 works for simple cases, but for money use BigDecimalClick to read tutorial: BigInteger and BigDecimal in Java with Examples.
  • Math.ceilDiv() (Java 18+) divides integers rounding up, without converting to double - ideal for "how many boxes" or "how many pages" calculations.
Random numbers - Math.random() Math.random() returns a random double from 0.0 (inclusive) up to, but not including, 1.0. To get a whole number in a range, scale and cast it: (int) (Math.random() * n) gives 0 to n - 1. For anything more, the java.util.Random class and ThreadLocalRandom are easier, and accept a range directly.
Generating random numbers
//RandomNumbers.java
import java.util.Random;
import java.util.concurrent.ThreadLocalRandom;

public class RandomNumbers {
  public static void main(String[] args) {
    double r = Math.random();
    System.out.println("0.0 <= r < 1.0 : " + (r >= 0.0 && r < 1.0));

    int[] counts = new int[7];
    for (int i = 0; i < 60_000; i++) {
      int die = (int) (Math.random() * 6) + 1;      // 1 to 6
      counts[die]++;
    }
    for (int face = 1; face <= 6; face++) {
      System.out.printf("face %d: about %.1f%%%n", face, counts[face] / 600.0);
    }

    Random seeded = new Random(42);                  // the same seed gives the same sequence
    System.out.println("Seeded Random   : " + seeded.nextInt(100) + " " + seeded.nextInt(100) + " " + seeded.nextInt(100));
    int between = ThreadLocalRandom.current().nextInt(10, 21);   // 10 to 20
    System.out.println("10 <= between <= 20 : " + (between >= 10 && between <= 20));
  }
}
 OUTPUT of the above code (the percentages vary slightly from run to run)
0.0 <= r < 1.0 : true
face 1: about 16.6%
face 2: about 16.6%
face 3: about 16.7%
face 4: about 16.6%
face 5: about 16.6%
face 6: about 16.9%
Seeded Random   : 30 63 48
10 <= between <= 20 : true
Each face came up about one sixth of the time. A Random created with a seed always produces the same sequence - useful for repeatable tests and simulations. None of these is suitable for passwords or security tokens; use java.security.SecureRandom for those. Detecting overflow - the exact methods Integer arithmetic silently wraps around on overflow, as explained in primitive data typesClick to read tutorial: Java Primitive Data Types and Their Ranges with Examples. The exact methods - addExact(), subtractExact(), multiplyExact(), incrementExact(), negateExact() and toIntExact() - do the same calculations but throw an ArithmeticException instead of returning a wrong answer.
Catching overflow with the exact methods
//ExactMath.java
public class ExactMath {
  public static void main(String[] args) {
    int bigValue = 2_000_000_000;
    System.out.println("bigValue * 2           = " + (bigValue * 2));
    try {
      System.out.println("multiplyExact(bigValue, 2) = " + Math.multiplyExact(bigValue, 2));
    } catch (ArithmeticException e) {
      System.out.println("multiplyExact threw    : " + e.getMessage());
    }
    System.out.println("multiplyExact as long  = " + Math.multiplyExact((long) bigValue, 2));

    long fileSize = 5_000_000_000L;
    try {
      int size = Math.toIntExact(fileSize);
    } catch (ArithmeticException e) {
      System.out.println("toIntExact threw       : " + e.getMessage());
    }
    System.out.println("Math.abs(Integer.MIN_VALUE) = " + Math.abs(Integer.MIN_VALUE));
  }
}
 OUTPUT of the above code
bigValue * 2           = -294967296
multiplyExact threw    : integer overflow
multiplyExact as long  = 4000000000
toIntExact threw       : integer overflow
Math.abs(Integer.MIN_VALUE) = -2147483648
Notice the last line: Math.abs(Integer.MIN_VALUE) is still negative, because +2,147,483,648 does not fit in an int. Math.absExact() (Java 15+) throws an exception in that case instead.
Trigonometry, logarithms and other methods
  • sin(), cos(), tan(), asin(), acos(), atan() and atan2(y, x) work in radians. Convert with toRadians() and toDegrees().
  • log(x) - natural logarithm (base e); log10(x) - base 10; exp(x) - ex.
  • floorDiv() and floorMod() - integer division and remainder which round towards negative infinity, so floorMod(-1, 7) is 6, not -1 - handy for wrapping around days of the week or clock hours.
  • clamp(value, min, max) (Java 21+) - keeps a value within a range.
Trigonometric, logarithmic and other methods
//OtherMath.java
public class OtherMath {
  public static void main(String[] args) {
    System.out.println("sin(30 deg)   = " + Math.sin(Math.toRadians(30)));
    System.out.println("cos(60 deg)   = " + Math.cos(Math.toRadians(60)));
    System.out.println("atan2(1, 1)   = " + Math.toDegrees(Math.atan2(1, 1)) + " degrees");
    System.out.println("log(E)        = " + Math.log(Math.E));
    System.out.println("log10(1000)   = " + Math.log10(1000));
    System.out.println("digits in 98765 = " + ((int) Math.log10(98765) + 1));
    System.out.println("-1 % 7        = " + (-1 % 7));
    System.out.println("floorMod(-1, 7) = " + Math.floorMod(-1, 7));
    System.out.println("clamp(150, 0, 100) = " + Math.clamp(150, 0, 100));
  }
}
 OUTPUT of the above code
sin(30 deg)   = 0.49999999999999994
cos(60 deg)   = 0.5000000000000001
atan2(1, 1)   = 45.0 degrees
log(E)        = 1.0
log10(1000)   = 3.0
digits in 98765 = 5
-1 % 7        = -1
floorMod(-1, 7) = 6
clamp(150, 0, 100) = 100
sin(30°) printed 0.49999999999999994 instead of 0.5 - another reminder that floating-point results are approximations. Compare them with a small tolerance, never with ==. Summary In this tutorial we first saw that java.lang.Math is a class of static methods, with the constants PI and E. We then used abs(), max(), min() and signum(), and calculated powers and roots - remembering that ^ is not a power operator. Next we compared floor(), ceil(), round() and rint(), and saw how they treat halves and negative numbers. We then generated random numbers, and caught overflow with the exact methods. Lastly, we used the trigonometric and logarithmic methods, floorMod() and clamp(). In the next tutorial, we will calculate exactly, without rounding errors or overflow, using BigInteger and BigDecimalClick to read tutorial: BigInteger and BigDecimal in Java with Examples.