Understanding Classes and Static Member Functions
Math functions must be understood by their mathematical purpose, input conventions, and return-value rules.
Why Math Functions Need Careful Reading
A common starting belief is that every function in the Math class behaves like an ordinary rounding or measurement tool. Under that belief, you might expect angles to be supplied in degrees, floor to return an int, and random to produce truly random values. The Math class does not work that way. Its static member functions each have specific input conventions and return-value rules, and learning those rules is more useful than memorizing function names in isolation.
In this article you will trace how several Math calls transform their inputs. Before reading each explanation, try to predict the result. The mismatch between your prediction and the actual rule is where most of the learning happens.
Calling Math Functions Without an Object
The functions in the Math class are static member functions. A static member function belongs to the class itself, so you call it by writing the class name, a dot, and the function name, such as Math.abs(x). You do not need to create a Math object first. The class name is the thing you write in front of the dot, and no object is involved in the call.
The Math class groups several families of functions. Math.pow(x, y) computes x raised to the power y. Math.exp(x) computes the number e raised to the power x. Math.log(x) computes the logarithm of x with base e, which is called the natural logarithm. These three are related but distinct operations, so it helps to read each function's name against its definition rather than assuming they are interchangeable.
Math.abs(x) computes the absolute value of x. It is an exception to a general pattern. Most Math functions return a double regardless of the numeric type of the parameter, but Math.abs(x) returns a value with the same type as its input. Math.abs(9) returns 9, and an int input produces an int result.
9
9
8.0
1.0
0.0Math.abs(9)andMath.abs(-9)both print an int, because the input is an int.Math.pow(2, 3)computes 2 raised to the power 3, and the result is a double, printed as 8.0.Math.exp(0)computes e raised to the power 0, which is 1.0.Math.log(1)computes the natural logarithm of 1, which is 0.0.
Radians Versus Degrees
Trigonometric functions use radians, and inverse trigonometric functions return radians. This is the most common source of surprise with the Math class. If you pass 90 to Math.sin, the computer treats 90 as 90 radians, not 90 degrees. Because a full turn is about 6.283 radians, 90 radians is many turns around the circle, and the sine of that angle is about 0.894, not 1.
A right angle is 90 degrees, and it corresponds to pi divided by 2 radians. To get the sine of a 90-degree angle, convert the angle to radians first by multiplying degrees by pi and dividing by 180. Passing Math.PI / 2 to Math.sin gives 1.0, which matches the sine of 90 degrees.
Floor, Round, and Ceil on Negative Values
Floor, round, and ceil use different rounding rules, and each one returns a double. Math.floor(x) moves a value down to the nearest whole number that is not greater than x. Math.ceil(x) moves a value up to the nearest whole number that is not less than x. Math.round(x) moves a value to the nearest whole number, and it has a specific tie-breaking rule for values exactly halfway between two integers.
Negative values are where the three functions are easiest to confuse. For -2.5, floor moves downward to -3.0, because -3 is the largest whole number that is not greater than -2.5 is wrong to say; the correct reading is that floor always moves toward negative infinity, so -2.5 goes down to -3.0. Ceil moves toward positive infinity, so -2.5 goes up to -2.0. Round, for a halfway value like -2.5, rounds toward positive infinity in Java, so it goes to -2 rather than -3.
-3.0
-2
-2.0
3floor(-2.5)moves down to -3.0.round(-2.5)lands on -2, because a halfway value rounds toward positive infinity.ceil(-2.5)moves up to -2.0.round(2.5)lands on 3, so the halfway tie moves in the opposite direction than it does for -2.5.
What do you think happens?
Before reading the answer, what do you think Math.round(-2.5) returns?
Reveal answer
-2
Java's Math.round sends a halfway value toward positive infinity. For -2.5, the nearest integers are -3 and -2, and the tie goes up to -2. For 2.5, the tie goes up to 3. This is why round(-2.5) and round(2.5) move in different directions relative to zero.
Mistakes with Rounding Functions
Common mistake Assuming floor and ceil always move toward zero.
What it looks likeMath.floor(-2.5) is -3.0, not -2.0.Why it failsFloor moves toward negative infinity and ceil moves toward positive infinity, so for negative values floor goes further from zero.
Do this insteadRead floor as going down on the number line and ceil as going up, even when the numbers are negative.
Common mistake Assuming round treats every halfway value the same way regardless of sign.
What it looks likeMath.round(-2.5) gives -2, but Math.round(2.5) gives 3.Why it failsRound with halfway values does not simply round away from zero; the tie goes toward positive infinity.
Do this insteadCheck the sign and the tie-breaking rule before predicting the result of round on a value ending in .5.
Common mistake Expecting floor to return an int.
What it looks likeMath.floor(7.9) returns 7.0, a double.Why it failsMath.floor(x)returns a double value.Do this insteadExpect a double result and convert explicitly if an int is needed.
Common mistake Expecting Math.sin to accept degrees directly, which produces a value far from the sine you intended.
Range and Pseudorandom Behavior of Math.random
Math.random() returns a randomly chosen double in the range from 0.0, inclusive, to 1.0, exclusive. Inclusive means 0.0 is a possible result. Exclusive means 1.0 is never returned. Every value the function produces therefore satisfies 0.0 <= result < 1.0.
The values are pseudorandom. The computer calculates them with a procedure rather than producing truly random values. The source describes them as effectively random enough for most purposes it covers, but a learner should remember that they are computed, not drawn from a physical source of randomness.
true- The printed number is different on each run, but the comparison is always true because the range includes 0.0 and excludes 1.0.
- The check uses the same inclusive and exclusive endpoints described in the range rule.
A common way to use this range is to scale the result. Multiplying Math.random() by 6 gives a value from 0.0 up to, but not including, 6.0. Taking the floor of that value and adding 1 produces a whole number from 1 through 6. This pattern follows directly from the range rule and the floor behavior described above.
Tracing Math Calls Step by Step
Without running the code, predict the printed value of each line: Math.floor(-7.2), Math.ceil(-7.2), Math.round(-7.2), and Math.round(7.5). Then state whether Math.random() could ever return exactly 1.0.
Hints
- Floor moves toward negative infinity, so floor of -7.2 is the next whole number below it.
- Ceil moves toward positive infinity, so ceil of -7.2 is the next whole number above it.
- Round goes to the nearest whole number; -7.2 is closer to -7, and 7.5 is a halfway value that rounds toward positive infinity.
Math.random()excludes its upper endpoint, 1.0.
Key Takeaways
- Math class functions are static, so you call them through the class name without creating a Math object.
- Trigonometric and inverse trigonometric functions in the Math class use radians, so convert degrees before calling them.
- Floor moves toward negative infinity, ceil moves toward positive infinity, and round sends halfway values toward positive infinity, so
round(-2.5)is -2 whileround(2.5)is 3. Math.random()returns a pseudorandom double from 0.0 inclusive to 1.0 exclusive, and it is computed rather than truly random.