As well as BigDecimal, decimals can have type Float or Double. Unlike BigDecimal which has no size limit, Float and Double are fixed-size, and thus more efficient in calculations. BigDecimal stores its value as base-10 digits, while Float and Double store their values as binary digits. So although using them is more efficient in calculations, the result of calculations will not be as exact as in base-10, eg, 3.1f + 0.4f computes to 3.499999910593033, instead of 3.5.

We can force a decimal to have a specific type other than BigDecimal by giving a suffix (F for Float, D for Double):

assert 1.200065d.class == Double
assert 1.234f.class == Float
assert (-1.23E23D).class == Double
assert (1.167g).class == BigDecimal
    //although g suffix here is optional, it makes examples more readable

We can enquire the minimum and maximum values for Floats and Doubles:

assert Float.MIN_VALUE == 1.4E-45f
assert Float.MAX_VALUE == 3.4028235E38f
assert Double.MIN_VALUE == 4.9E-324d
assert Double.MAX_VALUE == 1.7976931348623157E308d

We can represent infinities by using some predefined constants (prefixed by either Float or Double):

assert (1f / 0f) == Double.POSITIVE_INFINITY
assert (-1f / 0f) == Double.NEGATIVE_INFINITY
assert Double.POSITIVE_INFINITY == Float.POSITIVE_INFINITY

assert 0.0f != -(0.0f)
    //positive and negative zeroes not equal, when negative is written -(0.0f)
assert 0.0f == -0.0f
    //but when negative is written -0.0f, it's evaluated as positive

If a nonzero Double literal is too large or too small, it's represented by Double.POSITIVE_INFINITY or Double.NEGATIVE_INFINITY or 0.0:

assert Double.MAX_VALUE * Double.MAX_VALUE == Double.POSITIVE_INFINITY
assert Double.MIN_VALUE * Double.MIN_VALUE == 0.0d
assert -Double.MAX_VALUE * Double.MAX_VALUE == Double.NEGATIVE_INFINITY
assert -Double.MAX_VALUE * -Double.MAX_VALUE == Double.POSITIVE_INFINITY

Classes Float and Double can both be written uncapitalized, ie, float and double.

assert Float.TYPE == float
assert Double.TYPE == double

There's a special variable called Double.NaN (and Float.NaN), meaning "Not a Number", which is sometimes returned from math calculations. Once introduced into a math calculation, the result will (usually) be NaN.

Conversions

The Float and Double classes, along with BigDecimal, BigInteger, Integer, Long, Short, and Byte, can all be converted to one another.

Converting numbers to integers may involve rounding or truncation:

assert 45.76f as int == 45i  //truncated
assert 45.76d as int == 45i
assert 45.76f.toInteger() == 45i //method name
assert 45.76f.toLong() == 45L
assert 200.8f as byte == -56 as byte //sign reversed after truncation
assert 45.76f.toBigInteger() == 45

Converting from integers to float or double (may involve rounding):

assert 789g as Float == 789f
assert 45i.toFloat() == 45f //method name
assert 789g.toFloat() == 789f
assert 789g.floatValue() == 789f //alternative method name
assert 45i as double == 45d
assert 6789g.toDouble() == 6789d //method name
assert 6789g.doubleValue() == 6789d //alternative method name

assert new BigInteger( '1' + '0'*40 ).floatValue() == Float.POSITIVE_INFINITY
    //one with 40 zeroes after it
assert new BigInteger( '1234567890' * 3 ).floatValue() == 1.2345679e29f
    //precision lost on conversion

Converting from BigDecimal to float or double (may involve rounding):

assert 89.980 as float == 89.98f
assert 1.432157168 as float == 1.4321572f //rounded
assert 78.9g.toFloat() == 78.9f
assert 456.789g.floatValue() == 456.789f
assert 6.789g.toDouble() == 6.789d
assert 2345.6789g.doubleValue() == 2345.6789d
assert new BigDecimal( '-' + '1' *45 ).floatValue() == Float.NEGATIVE_INFINITY
assert new BigDecimal( '0.' + '0'*45 + '1' ).floatValue() == 0.0f
assert new BigDecimal( '0.' + '1234567890' *3 ).floatValue() == 0.12345679f
                                                //precision lost on conversion

We can convert a double to a float. but there's no Double() constructor accepting a float as an argument.

assert 23.45e37d as float == 23.45e37f
assert new Float( 23.45e37d ) == 23.45e37f
assert new Float( 23.45e67d ) == Float.POSITIVE_INFINITY
assert 123.45e12f as double //conversion inexact

We can create a Float or Double from a string representation of the number, either base-10 or hex:

[ '77', '1.23e-23', '4.56', '-1.7E1', '98.7e2', '-0.27e-30' ].each{
  assert it.toFloat()
  assert new Float(it)
  assert it.toDouble()
  assert new Double(it)
}
assert new Float( '   1.23e-23    ' ) //leading and trailing whitespace removed
try{ new Float( null ); assert 0 }
catch(e){ assert e instanceof NullPointerException }
[ 'NaN', '-NaN', 'Infinity', '-Infinity', '+Infinity' ].each{
  assert new Float(it)
}

assert new Float( '  -0Xabc.defP7' )
    //we can have hexadecimal mantissa, with P indicating exponent
assert new Float( '  0xABC.DEFp17  ' )
    //part after P must be base-10, not more hex
assert new Float( '0X.defP-3f  \n' )
    //any whitespace OK (spaces, tabs, newlines, carriage returns, etc)
try{ new Float( '  @0X6azQ/3d' ); assert 0 }
catch(e){ assert e instanceof NumberFormatException }
    //because the string doesn't contain a parsable number in the form of a Float
assert Float.valueOf( '0xABp17' )
    //alternate means of contructing float from string representation
assert Float.parseFloat( '0xABp17' )
    //another alternate means of contructing float from string
assert new Double( '0x12bc.89aP7d  ' )

The string is first converted to a double, then if need be converted to a float.

Converting from double to BigDecimal is only exact when the double has an exact binary representation, eg, 0.5, 0.25. If a float is supplied, it's converted to a double first, then given to the BigDecimal constructor. The scale of the returned BigDecimal is the smallest value such that (10**scale * val) is an integer.

assert new BigDecimal(0.25d) == 0.25
    //exact conversion because 0.25 has an exact binary representation

assert new BigDecimal(0.1d) ==
    0.1000000000000000055511151231257827021181583404541015625

(0.1d).toBigDecimal() == new BigDecimal(0.1d) //alternative method name

assert new BigDecimal(0.1f) == 0.100000001490116119384765625
    //inexact conversion as 0.1 has a recurring decimal part in binary

assert (0.1f as BigDecimal) == 0.100000001490116119384765625

assert new BigDecimal(0.1d, new java.math.MathContext(25) ) ==
    0.1000000000000000055511151 //rounds to 25 places as specified

A more exact way to convert a double to a BigDecimal:

assert BigDecimal.valueOf( 0.25d ) == 0.25
assert BigDecimal.valueOf( 0.1d ) == 0.1
    //always exact, because converts double to a string first
assert new BigDecimal( Double.toString( 0.1d ) ) == 0.1
    //explicitly convert double to string, then to BigDecimal
assert BigDecimal.valueOf( -23.456e-17d ) == -2.3456E-16
assert BigDecimal.valueOf( -23.456e-17f ) == -2.3455999317674643E-16
    //result inexact because float converted to double first

try{ BigDecimal.valueOf( Double.POSITIVE_INFINITY ); assert 0 }
catch(e){ assert e instanceof NumberFormatException }

try{ BigDecimal.valueOf( Double.NaN ); assert 0 }
catch(e){ assert e instanceof NumberFormatException }
    //however, infinities and NaN won't convert that way

We can convert a float or double to a unique string representation in base-10. There must be at least one digit to represent the fractional part, and beyond that as many, but only as many, more digits as are needed to uniquely distinguish the argument value from adjacent values of type float. (The returned string must be for the float value nearest to the exact mathematical value supplied; if two float representations are equally close to that value, then the string must be for one of them and the least significant bit of the mantissa must be 0.)

assert Float.toString( 3.0e6f ) == '3000000.0' //no leading zeros
assert Float.toString( 3.0e0f ) == '3.0' //at least one digit after the point
assert Float.toString( 3.0e-3f ) == '0.0030'
assert Float.toString( 3.0e7f ) == '3.0E7'
    //exponent used if it would be > 6 or < -3
assert Float.toString( 3.0e-4f ) == '3.0E-4' //mantissa >= 1 and < 10

We can also convert a float or double to a hexadecimal string representation:

[        0.0f: '0x0.0p0',
      (-0.0f): '0x0.0p0', //no negative sign in hex string rep'n of -0.0f
         1.0f: '0x1.0p0', //most returned strings begin with '0x1.' or '-0x1.'
         2.0f: '0x1.0p1',
         3.0f: '0x1.8p1',
         5.0f: '0x1.4p2',
      (-1.0f): '-0x1.0p0',
         0.5f: '0x1.0p-1',
        0.25f: '0x1.0p-2',
          (Float.MAX_VALUE): '0x1.fffffep127',
          (Float.MIN_VALUE): '0x0.000002p-126',
                       //low values beginning with '0x0.' are called 'subnormal'
  (Float.NEGATIVE_INFINITY): '-Infinity',
                (Float.NaN): 'NaN',
].each{ k, v->
  assert Float.toHexString(k) == v
}

We can format integers and decimals using String.format():

//Integers ('d')
assert String.format('%d', 45) == '45'
assert String.format('%5d,%1$5o', 46L) == '   46,   56'
    //octal format; each minimum 5 chars wide; use an argument twice
assert String.format('%-4d,%<-5x', 47g) == '47  ,2f   '
    //hex format without leading '0x'; left-justified with '-';
    //shortcut ('<') for using argument again
assert String.format('%2d,%<1X', 123) == '123,7B'
    //hex in uppercase with capital 'X'
assert String.format('%04d', 34) == '0034' //zero-pad
assert String.format('%,5d', 12345) == '12,345' //use grouping-separators
assert String.format('%+3d,%2$ 3d', 123L, 456g) == '+123, 456'
    //always use plus sign; always use a leading space
assert String.format('%(3d', -789 as short) == '(789)' //parens for negative
assert String.format('%(3o,%2$(3x,%3$(3X', 123g, 456g, -789g) == '173,1c8,(315)'
    //neg octal/hex only for BigInteger

//Floating-Point ('f', 'a', 'e', 'g')
assert String.format('e = %f', Math.E) == 'e = 2.718282'
    //default 'f' format is 7.6
assert String.format('e=%+6.4f', Math.E) == 'e=+2.7183'
    //precision is digits after decimal point
assert String.format('$ %(,6.2f', -6217.58) == '$ (6,217.58)'
    //'(' flag gives parens, ',' uses separators
assert String.format('%a, %A', 2.7182818f, Math.PI) ==
    '0x1.5bf0a8p1, 0X1.921FB54442D18P1' //'a' for hex
assert String.format('%+010.4a', 23.25d) == '+0x001.7400p4'
    //'+' flag always includes sign; '0' flag zero-fills
assert String.format('%e, %10.4e', Math.E, 12345.6789) ==
    '2.718282e+00, 1.2346e+04' //'e' for scientific format
assert String.format('%(10.5E', -0.0000271) == '(2.71000E-05)'
assert String.format('%g, %10.4G', Math.E, 12345.6789) == '2.71828,  1.235E+04'
    //'f' or 'e', depending on input

Floating-Point Arithmetic

We can perform the same basic operations that integers and BigDecimal can:

assert 3.4f.plus( 3.3f ) == 3.4f + 3.3f
assert 3.4f.minus( 2.1f ) == 3.4f - 2.1f
assert 3.0f.multiply( 3.1f ) == 3.0f * 3.1f
assert 3.0f.multiply( 3f ) == 3.0f * 3f
assert 3.0.multiply( 3f ) == 3.0 * 3f
assert 7.7f.negate() == -7.7f //unary operation/method
assert (-7.7f).negate() == -(-7.7f)
assert +(7.7f) == 7.7f

try{ 3.4f.multiply(null); assert false }
catch(e){ assert e instanceof NullPointerException }
    //methods throw NullPointerException if passed a null

For + - and *, anything with a Double or Float converts both arguments to a Double:

assert (23.4f + 7.998d).class == Double
assert (23.4f - 123.45g).class == Double
assert (7.998d * 123.45g).class == Double
assert (23.4f - i=789).class == Double

We can divide using floats and doubles:

assert 2.4f.div( 1.6f ) == ( 2.4f / 1.6f )
assert ( 2.5f / 1i ).class == Double
    //produces double result if either operand is float or double
assert ( 2.5f / 1.25 ).class == Double

We can perform mod on floats and doubles:

def a= 34.56f % 5
assert a == 34.56f.mod(5) && a < 5.0f && a >= 0.0f

def b= 34.56f % 5.1f
assert b == 34.56f.mod(5.1f) && b < 5.0f && b >= 0.0f

def c= -34.56f % 5.1f
assert c == (-34.56f).mod(5.1f) && c <= 0.0f && c > -5.0f

IEEEremainder resembles mod in some ways:

def Infinity=Double.POSITIVE_INFINITY, NaN=Double.NaN, Zero=0.0d
assert Math.IEEEremainder( 33d, 10d ) == 3d
                               //give remainder after rounding to nearest value
assert Math.IEEEremainder( 37d, 10d ) == -3d
assert Math.IEEEremainder( -33d, 10d ) == -3d
assert Math.IEEEremainder( -37d, 10d ) == 3d
assert Math.IEEEremainder( 35d, 10d ) == -5d
                               //when two values equally near, use even number
assert Math.IEEEremainder( 45d, 10d ) == 5d
assert Math.IEEEremainder( Zero, 10d ) == Zero
assert Math.IEEEremainder( -Zero, 10d ) == -Zero
assert Math.IEEEremainder( Infinity, 10d ) == NaN
assert Math.IEEEremainder( 35d, Zero ) == NaN
assert Math.IEEEremainder( 35d, Infinity ) == 35d

We can perform other methods:

assert (-23.4f).abs() == 23.4f
assert (-23.414d).abs() == 23.414d

assert 14.49f.round() == 14i
assert 14.5f.round() == 15i
assert (-14.5f).round() == -14i
assert 14.555d.round() == 15L

We can raise a float or double to a power:

assert 4.5f**3 == 91.125d //double returned
assert 4.5f.power(3) == 4.5f**3 //using equivalent method instead
assert 1.1.power(1000000000) == Double.POSITIVE_INFINITY

We can test whether a float or double is a number and whether it's an infinite number:

def Infinity=Double.POSITIVE_INFINITY, NaN=Double.NaN, Zero=0.0d
assert NaN.isNaN()
assert Double.isNaN( NaN )
assert Infinity.isInfinite()
assert (-Infinity).isInfinite()
assert Double.isInfinite( Infinity )
assert Double.isInfinite( -Infinity )
assert Float.isInfinite( Float.NEGATIVE_INFINITY )

We can test whether two floats or doubles have equal values using operators or methods:

assert 345f.equals( 3.45e2f ) && 345f == 3.45e2f
    //equals() and == behave the same in all cases
assert ! 34.5f.equals( 13.4f ) && 34.5f != 13.4f //equivalent

assert Float.NaN.equals( Float.NaN ) && Float.NaN == Float.NaN

assert 0.0f == -0.0f && 0.0f.equals( -0.0f )
    //-0.0f is evaluated as positive zero
assert 0.0f != -(0.0f) && ! 0.0f.equals( -(0.0f) )
    //negative zero must be written -(0.0f)

assert 345d.equals( 3.45e2d ) && 345d == 3.45e2d

assert Float.POSITIVE_INFINITY.equals( Float.POSITIVE_INFINITY ) &&
    Float.POSITIVE_INFINITY == Float.POSITIVE_INFINITY
assert ! Float.POSITIVE_INFINITY.equals( Float.NEGATIVE_INFINITY ) &&
    ! ( Float.POSITIVE_INFINITY == Float.NEGATIVE_INFINITY )

We can compare floats and doubles using the <=> operator, the compareTo() method, and the compare() static method:

assert (2.50f <=> 2.5f) == 0 && 2.50f.compareTo(2.5f) == 0
assert (-3.45f <=> 1.23f) == -1 && (-3.45f).compareTo(1.23f)  == -1
assert (1.23d <=> -0.12d) == 1 && 1.23d.compareTo(-0.12d) == 1
assert (-1.23d < -0.12d) && (-1.23d).compareTo(-0.12d) < 0

assert (Float.NaN > Float.POSITIVE_INFINITY) &&
    Float.NaN.compareTo(Float.POSITIVE_INFINITY) > 0
assert (0.0f <=> -0.0f) == 0
assert (Float.NaN <=> Float.NaN) == 0 && Float.NaN.compareTo(Float.NaN) == 0
assert Float.compare( 3.4f, 7.9f ) == -1
assert Double.compare( 3.4d, -7.9d ) == 1

Auto-incrementing and -decrementing work on floats and doubles:

def a= 12.315d
a++
assert a == 13.315d
--a
assert a == 12.315d

Non-zero floats and doubles evaluate as true in boolean contexts:

assert (1.23d? true: false)
assert ! (0.0f? true: false)

Bitwise Operations

We can convert a float to the equivalent int bits, or a double to equivalent float bits. For a float, bit 31(mask 0x80000000) is the sign, bits 30-23 (mask 0x7f800000) are the exponent, and bits 22-0 (mask 0x007fffff) are the mantissa. For a double, bit 63 is the sign, bits 62-52 are the exponent, and bits 51-0 are the mantissa.

assert Float.floatToIntBits( 0.0f ) == 0
assert Float.floatToIntBits( 15.15f ) == 0x41726666
assert Float.floatToIntBits( Float.NaN ) == 0x7fc00000
assert Float.floatToIntBits( Float.POSITIVE_INFINITY ) == 0x7f800000
assert Float.floatToIntBits( Float.NEGATIVE_INFINITY ) == (0xff800000 as int)
assert Double.doubleToLongBits( 15.15d ) == 0x402e4ccccccccccd

The methods floatToRawIntBits() and doubleToRawLongBits() act similarly, except that they preserve Not-a-Number (NaN) values. So If the argument is NaN, the result is the integer or long representing the actual NaN value produced from the last calculation, not the canonical Float.NaN value to which all the bit patterns encoding a NaN can be collapsed (ie, 0x7f800001 through 0x7fffffff and 0xff800001 through 0xffffffff).

The intBitsToFloat() and longBitsToDouble() methods act oppositely. In all cases, giving the integer resulting from calling Float.floatToIntBits() or Float.floatToRawIntBits() to the intBitsToFloat(int) method will produce the original floating-point value, except for a few NaN values. Similarly with doubles. These methods are the only operations that can distinguish between two NaN values of the same type with different bit patterns.

assert Float.intBitsToFloat( 0x7fc00000 ) == Float.NaN
assert Float.intBitsToFloat( 0x7f800000 ) == Float.POSITIVE_INFINITY
assert Float.intBitsToFloat( 0xff800000 as int ) == Float.NEGATIVE_INFINITY
assert Float.intBitsToFloat( 0 ) == 0.0f
assert Float.intBitsToFloat( 0x41726666 ) == 15.15f
assert Double.longBitsToDouble( 0x402e4ccccccccccd ) == 15.15d
assert Float.intBitsToFloat( Float.floatToIntBits( 15.15f ) ) == 15.15f

As well as infinities and NaN, both Float and Double have other constants:

assert Float.MAX_VALUE == Float.intBitsToFloat(0x7f7fffff)
assert Float.MIN_NORMAL == Float.intBitsToFloat(0x00800000)
    //the smallest positive nonzero normal value
assert Float.MIN_VALUE == Float.intBitsToFloat(0x1)
    //the smallest positive nonzero value, including subnormal values
assert Float.MAX_EXPONENT == Math.getExponent(Float.MAX_VALUE)
assert Float.MIN_EXPONENT == Math.getExponent(Float.MIN_NORMAL)
assert Float.MIN_EXPONENT == Math.getExponent(Float.MIN_VALUE) + 1
    //for subnormal values

Floating-Point Calculations

There are two constants of type Double, Math.PI and Math.E, that can't be represented exactly, not even as a recurring decimal.

The trigonometric functions behave as expected with the argument in radians, but 0.0 isn't represented exactly. For example, sine:

assert Math.sin( 0.0 ) == 0.0
assert Math.sin( 0.5 * Math.PI ) == 1.0
assert Math.sin( Math.PI ) < 1e-15 //almost 0.0, but not quite
assert Math.sin( 1.5 * Math.PI ) == -1.0
assert Math.sin( 2 * Math.PI ) > -1e-15 //almost 0.0
assert Math.sin( -0.5 * Math.PI ) == -1.0
assert Math.sin( -Math.PI ) > -1e-15 //almost 0.0
assert Math.sin( -1.5 * Math.PI ) == 1.0
assert Math.sin( -2 * Math.PI ) < 1e-15 //almost 0.0
assert Math.sin( Double.POSITIVE_INFINITY ) == Double.NaN
assert Math.sin( Double.NEGATIVE_INFINITY ) == Double.NaN

Other trig functions are:

assert Math.cos( Double.POSITIVE_INFINITY ) == Double.NaN
assert Math.tan( Double.NEGATIVE_INFINITY ) == Double.NaN
assert Math.asin( 0.0 ) == 0.0
assert Math.asin( 1.0 ) == 0.5 * Math.PI
assert Math.asin( 1.001 ) == Double.NaN
assert Math.acos( -1.0 ) == Math.PI
assert Math.acos( -1.001 ) == Double.NaN
assert Math.atan( 0.0 ) == 0.0

Some logarithmic functions:

def Infinity= Double.POSITIVE_INFINITY, NaN= Double.NaN, Zero= 0.0d

[ (Infinity): Infinity,
       10000: 4,
          10: 1,
           1: 0,
         0.1: -1,
     0.00001: -5,
         0.0: -Infinity,
    (-0.001): NaN,
].each{ k, v -> assert Math.log10(k) == v } //returns base-10 logarithm

[ (Infinity): Infinity,
    (Math.E): 1,
           1: 0,
         0.0: -Infinity,
    (-0.001): NaN,
].each{ k, v -> assert Math.log(k) == v } //returns natural logarithm

assert Math.exp( Infinity ) == Infinity //returns Math.E raised to a power
assert Math.exp( -Infinity ) == 0.0

Math.ulp(d) returns the size of the units of the last place for doubles (the difference between the value and the next larger in magnitude).

assert Math.ulp( 123.456d ) == Math.ulp( -123.456d )
assert Math.ulp( 0.123456789d ) != Math.ulp( 0.123456789f )
    //if Float, a different scale is used

assert Math.ulp( Double.POSITIVE_INFINITY ) == Double.POSITIVE_INFINITY
assert Math.ulp( Double.NEGATIVE_INFINITY ) == Double.POSITIVE_INFINITY
assert Math.ulp( 0.0d ) == Double.MIN_VALUE
assert Math.ulp( Double.MIN_VALUE ) == Double.MIN_VALUE
assert Double.MAX_VALUE > Math.ulp( Double.MAX_VALUE )

Accuracy of the Math methods is measured in terms of such ulps for the worst-case scenario.If a method always has an error less than 0.5 ulps, the method always returns the floating-point number nearest the exact result, and so is always correctly rounded. However, doing this and maintaining floating-point calculation speed together is impractical. Instead, for the Math class, a larger error bound of 1 or 2 ulps is allowed for certain methods. But most methods with more than 0.5 ulp errors are still required to be semi-monotonic, ie, whenever the mathematical function is non-decreasing, so is the floating-point approximation, and vice versa. Not all approximations that have 1 ulp accuracy meet the monotonicity requirements. sin, cos, tan, asin, acos, atan, exp, log, and log10 give results within 1 ulp of the exact result that are semi-monotonic.

Further Calculations

We can find the polar coordinate of two (x,y) coordinates. The result is within 2 ulps of the exact result, and is semi-monotonic.

def Infinity= Double.POSITIVE_INFINITY, NaN= Double.NaN, Zero= 0.0d

[     [ 1d, 1d ]: 0.25d * Math.PI,
     [ 1d, -1d ]: 0.75d * Math.PI,
     [ -1d, 1d ]: -0.25d * Math.PI,
    [ -1d, -1d ]: -0.75d * Math.PI,

      [ 0d, 1d ]: 0d,
   [ -(0d), 1d ]: -(0d),
     [ 0d, -1d ]: Math.PI,
  [ -(0d), -1d ]: -Math.PI, // -(0d) gives huge difference in result to 0d 
      [ 1d, 0d ]: 0.5d * Math.PI,
   [ 1d, -(0d) ]: 0.5d * Math.PI,
     [ -1d, 0d ]: -0.5d * Math.PI,
  [ -1d, -(0d) ]: -0.5d * Math.PI,

   [ Double.NaN, 1d ]: Double.NaN, //NaN returned if either argument is NaN

          [ 1d, Infinity ]: 0d,
         [ 1d, -Infinity ]: Math.PI,
         [ -1d, Infinity ]: -(0d),
        [ -1d, -Infinity ]: -Math.PI,
          [ Infinity, 1d ]: 0.5d * Math.PI,
         [ Infinity, -1d ]: 0.5d * Math.PI,
         [ -Infinity, 1d ]: -0.5d * Math.PI,
        [ -Infinity, -1d ]: -0.5d * Math.PI,
    [ Infinity, Infinity ]: 0.25d * Math.PI,
   [ Infinity, -Infinity ]: 0.75d * Math.PI,
   [ -Infinity, Infinity ]: -0.25d * Math.PI,
  [ -Infinity, -Infinity ]: -0.75d * Math.PI,
].each{k,v->
  if( Math.atan2( k[0], k[1] ) != v )
        println "( ${k[0]}, ${k[1]} ): ${Math.atan2(k[0],k[1])};  $v"
}

We can perform the hyperbolic trigonometric functions:

assertClose= {it1,it2,ulp->
  assert it1 > it2 - ulp*Math.ulp(it2) && it1 < it2 + ulp*Math.ulp(it2)
}
def Infinity=Double.POSITIVE_INFINITY, Zero=0d, NaN=Double.NaN, E=Math.E
assertClose Math.sinh( 2d ), 0.5d*(E**2d - E**-2d), 2.5d
    //sinh() result will be with 2.5 ulp of exact value
assert Math.sinh( Infinity ) == Infinity
assert Math.sinh( -Infinity ) == -Infinity
assert Math.sinh( Zero ) == Zero
assert Math.sinh( -Zero ) == -Zero
assertClose Math.cosh( 2d ), 0.5d*(E**2d + E**-2d), 2.5d
assert Math.cosh( Infinity ) == Infinity
assert Math.cosh( -Infinity ) == Infinity
assert Math.cosh( Zero ) == 1d
assert Math.cosh( -Zero ) == 1d
assertClose Math.tanh( 2d ), Math.sinh( 2d )/Math.cosh( 2d ), 2.5d
assert Math.tanh( Infinity ) == 1d
assert Math.tanh( -Infinity ) == -1d
assert Math.tanh( Zero ) == Zero
assert Math.tanh( -Zero ) == -Zero
    //once the exact result of tanh is within 1/2 of an ulp of 
    //the limit value of +/- 1, a correctly signed +/- 1.0 will be returned

We can convert between degrees and radians. The conversion is generally inexact.

assert Math.toDegrees( Math.PI ) == 180.0
assert Math.toRadians( 90.0 ) == 0.5 * Math.PI

We can calculate (E**x)-1 (1 + x) in one call. For values of x near 0, Math.expm1( x ) + 1d is much closer than Math.exp( x ) to the true result of e**x. The result will be semi-monotonic, and within 1 ulp of the exact result. Once the exact result of e**x - 1 is within 1/2 ulp of the limit value -1, -1d will be returned.

assertClose= {it1,it2,ulp->
  assert it1 > it2 - ulp*Math.ulp(it2) && it1 < it2 + ulp*Math.ulp(it2)
}
def Infinity=Double.POSITIVE_INFINITY, NaN=Double.NaN, Zero= 0d, E= Math.E

assertClose Math.expm1( 123.4d ), E**123.4d - 1, 31
assertClose Math.expm1( 23.4d ), E**23.4d - 1, 10
assertClose Math.expm1( 3.4d ), E**3.4d - 1, 3
assert Math.expm1( Infinity ) == Infinity
assert Math.expm1( -Infinity ) == -1d
assert Math.expm1( Zero ) == Zero
assert Math.expm1( -Zero ) == -Zero

We can also calculate ln(1 + x) in one call. For small values of x, Math.log1p( x ) is much closer than Math.log(1d + x) to the true result of ln(1 + x). The result will be semi-monotonic, and within 1 ulp of the exact result.

def Infinity=Double.POSITIVE_INFINITY, NaN=Double.NaN, Zero= 0d
assert Math.log1p( 123.4d ) == Math.log(1d + 123.4d)
assert Math.log1p( 23.4d ) == Math.log(1d + 23.4d)
assert Math.log1p( 3.4d ) == Math.log(1d + 3.4d)
assert Math.log1p( -1.1d ) == NaN
assert Math.log1p( Infinity ) == Infinity
assert Math.log1p( -1d ) == -Infinity
assert Math.log1p( Zero ) == Zero
assert Math.log1p( -Zero ) == -Zero

Scale binary scalb(x,y) calculates (x * y**2) using a single operation, giving a more accurate result. If the exponent of the result would be larger than Float/Double.MAX_EXPONENT, an infinity is returned. If the result is subnormal, precision may be lost. When the result is non-NaN, the result has the same sign as x.

def Infinity= Double.POSITIVE_INFINITY, NaN= Double.NaN, Zero= 0.0d
assert Math.scalb(5, 3) == 5 * 2**3
assert Math.scalb(NaN, 3) == NaN
assert Math.scalb(Infinity, 3) == Infinity //same sign
assert Math.scalb(Zero, 3) == Zero //same sign

We have square root and cube root methods. For cbrt, the computed result must be within 1 ulp of the exact result.

def ten= Math.sqrt( 10 ) * Math.sqrt( 10 )
def error= 1e-14
assert ten > 10 - error && ten < 10 + error

assert Math.sqrt( -0.001 ) == Double.NaN
assert Math.sqrt( 0 ) == 0
assert Math.sqrt( Double.POSITIVE_INFINITY ) == Double.POSITIVE_INFINITY

def ten= Math.cbrt( 10 ) * Math.cbrt( 10 ) * Math.cbrt( 10 )
def error= 1e-14
assert ten > 10 - error && ten < 10 + error

assert Math.cbrt( -123.456 ) == -Math.cbrt( 123.456 )
assert Math.cbrt( 0 ) == 0
assert Math.cbrt( Double.POSITIVE_INFINITY ) == Double.POSITIVE_INFINITY
assert Math.cbrt( Double.NEGATIVE_INFINITY ) == Double.NEGATIVE_INFINITY

We can find the ceiling and floor of doubles:

assert Math.ceil( 6.77 ) == 7 &&      Math.floor( 6.77 ) == 6
assert Math.ceil( -34.43 ) == -34 &&  Math.floor( -34.43 ) == -35
assert Math.ceil( 0.73 ) == 1.0 &&    Math.floor( 0.73 ) == 0.0
assert Math.ceil( -0.73 ) == -0.0d && Math.floor( -0.73 ) == -1.0
    //sign required for -0.0d
assert Math.ceil( 13.0 ) == 13.0 &&   Math.floor( 13.0 ) == 13.0
assert Math.ceil( 0.0 ) == 0.0 &&     Math.floor( 0.0 ) == 0.0
assert Math.ceil( 23.45 ) == -Math.floor( -23.45 )
    //Math.ceil(x) always equals -Math.floor(-x)

We can round doubles to the nearest long (or floats to the nearest integer). The calculation is Math.floor(a + 0.5d) as Long, or Math.floor(a + 0.5f) as Integer

[                       7.45: 7,
                         7.5: 8,
                     (-3.95): -4,
                      (-3.5): -3,
                (Double.NaN): 0,
  (Double.NEGATIVE_INFINITY): Long.MIN_VALUE,
  (Long.MIN_VALUE as Double): Long.MIN_VALUE,
  (Double.POSITIVE_INFINITY): Long.MAX_VALUE,
  (Long.MAX_VALUE as Double): Long.MAX_VALUE,
].each{ k, v -> assert Math.round( k ) == v }

Unlike the numerical comparison operators, max() and min() considers negative zero to be strictly smaller than positive zero. If one argument is positive zero and the other negative zero, the result is positive zero.

assert Math.max( 7i, 9i ) == 9i //returns the same class as its arguments
assert Math.min( 23L, 19L ) == 19L
assert Math.min( 1.7f, 0.3f ) == 0.3f
assert Math.min( -6.7d, 1.3d ) == -6.7d
assert Math.min( 7i, 9L ) == 7L //converts result to most precise type of argument
assert Math.min( 1L, 3.3f ) == 1f
assert Math.min( -6.7f, 1.3d ) == -6.699999809265137d

Some other methods:

[   7.49d: 7.0d,
     7.5d: 8.0d,
     8.5d: 8d,
  (-7.5d): -8d,
       7d: 7d,
       0d: 0d,
 (Double.POSITIVE_INFINITY): Double.POSITIVE_INFINITY,
].each{ k, v-> assert Math.rint( k ) == v }
    //round to nearest integer (or even integer)

assert Math.abs( -23i ) == 23i
assert Math.abs( 234L ) == 234L
assert Math.abs( 0i ) == 0i
assert Math.abs( Integer.MIN_VALUE ) == Integer.MIN_VALUE
                              //WARNING: this result not intuitive
assert Math.abs( Long.MIN_VALUE ) == Long.MIN_VALUE

assert Math.abs( -23.45f ) == 23.45f
assert Math.abs( -123.4d ) == 123.4d
assert Math.abs( 0.0f ) == 0.0f
assert Math.abs( -0.0f ) == 0.0f
assert Math.abs( Float.NEGATIVE_INFINITY ) == Float.POSITIVE_INFINITY 

[ -23.45f, 781.23f, Float.NEGATIVE_INFINITY ].each{
  assert Math.abs(it) ==
      Float.intBitsToFloat(0x7fffffff & Float.floatToIntBits(it))
  assert Math.abs(it) ==
      Float.intBitsToFloat((Float.floatToIntBits(it)<<1)>>>1) 
} //there's related assertions for doubles

The pow() method returns the value of the first argument raised to the power of the second argument. If both arguments are integers, then the result is exactly equal to the mathematical result of raising the first argument to the power of the second argument if that result can in fact be represented exactly as a double value. Otherwise, special rules exist for processing zeros and infinities:

def Infinity= Double.POSITIVE_INFINITY, NaN= Double.NaN
[
  [ 3d, 0d ]: 1d,
  [ 3d, -(0d) ]: 1d,
  [ 3d, 1d ]: 3d,
  [ 3d, Infinity ]: Infinity,
  [ -3d, Infinity ]: Infinity,
  [ 0.3d, -Infinity ]: Infinity,
  [ -0.3d, -Infinity ]: Infinity,
  [ 3d, -Infinity ]: 0d,
  [ -3d, -Infinity ]: 0d,
  [ 0.3d, Infinity ]: 0d,
  [ -0.3d, Infinity ]: 0d,
  [ 1d, Infinity ]: Double.NaN,
  [ 0d, 1d ]: 0d,
  [ Infinity, -1d ]: 0d,
  [ 0d, -1d ]: Infinity,
  [ Infinity, 1d ]: Infinity,
  [ -(0d), 2d ]: 0d, //exponent >0 but not finite odd integer
  [ -Infinity, -2d ]: 0d, //exponent <0 but not finite odd integer
  [ -(0d), 3d ]: -(0d), //exponent is positive finite odd integer
  [ -Infinity, -3d ]: -(0d), //exponent is negative finite odd integer
  [ -(0d), -2d ]: Infinity, //exponent <0 but not finite odd integer
  [ -Infinity, 2d ]: Infinity, //exponent >0 but not finite odd integer
  [ -(0d), -3d ]: -Infinity, //exponent is negative finite odd integer
  [ -Infinity, 3d ]: -Infinity, //exponent is positive finite odd integer
  [ -3d, 4i ]: {-> def a= Math.abs(-3d); a*a*a*a }(),
                                //exponent is finite even integer
  [ -3d, 5i ]: {-> def a= Math.abs(-3d); -a*a*a*a*a }(),
                                //exponent is finite odd integer
  [ -3d, 2.5 ]: NaN, //exponent is finite and not an integer
  [ NaN, 0d ]: 1d //exception to the NaN ripple rule
].each{k, v->
  assert Math.pow( k[0], k[1] ) == v
}

More methods:

assert Math.random() >= 0d //this method uses new Random() when first called
assert Math.random() < 1d

assert Math.signum( 17.75d ) == 1d
assert Math.signum( 17.75f ) == 1f
assert Math.signum( -19.5d ) == -1d
assert Math.signum( 0d ) == 0d
assert Math.signum( -(0d) ) == -(0d)

We can use copySign() to return a first argument with the sign of the second argument.

assert Math.copySign( 34.4f, -2.1f ) == -34.4f
assert Math.copySign( -1234.4d, 2.23d ) == 1234.4d

We can compute the hypotenuse with risk of intermediate overflow (or underflow). The computed result is within 1 ulp of the exact result. If one parameter is held constant, the results will be semi-monotonic in the other parameter.

def Infinity=Double.POSITIVE_INFINITY, NaN=Double.NaN
assert Math.hypot( 9d, 16d ) == Math.sqrt( 9d**2 + 16d**2 )
assert Math.hypot( Infinity, 234d ) == Infinity
assert Math.hypot( NaN, 234d ) == NaN
assert Math.hypot( Infinity, NaN ) == Infinity

We can get the exponent from the binary representation of a double or float:

def Infinity=Double.POSITIVE_INFINITY, Zero=0d, NaN=Double.NaN, E=Math.E
assert Math.getExponent(2.345e31d) <= Double.MAX_EXPONENT
assert Math.getExponent(2.345e31d) >= Double.MIN_EXPONENT
assert Math.getExponent( NaN ) == Double.MAX_EXPONENT + 1
assert Math.getExponent( Infinity ) == Double.MAX_EXPONENT + 1

assert Math.getExponent( Zero ) == Double.MIN_EXPONENT - 1
    //this is also the value of subnormal exponents

assert Math.getExponent(12.3e4f) <= Float.MAX_EXPONENT &&
    Math.getExponent(12.3e4f) >= Float.MIN_EXPONENT

We can return the floating point number adjacent to the first arg in the direction of the second arg:

def Infinity=Double.POSITIVE_INFINITY, NaN=Double.NaN, Zero= 0d
assert Math.nextAfter( 12.34d, 999d ) == 12.34d + Math.ulp( 12.34d )
assert Math.nextAfter( 12.34d, -999d ) == 12.34d - Math.ulp( 12.34d )
assert Math.nextAfter( 12.34f, 999f ) == 12.34f + Math.ulp( 12.34f )
assert Math.nextAfter( 12.34d, 12.34d ) == 12.34d
    //if numbers equal, return second one
assert Math.nextAfter( Zero, -Zero ) == -Zero
    //numbers are 'equal', and second one returned
assert Math.nextAfter( Double.MIN_VALUE, -12d ) == Zero
assert Math.nextAfter( -Double.MIN_VALUE, 12d ) == -Zero
assert Math.nextAfter( Double.MAX_VALUE, Infinity ) == Infinity
assert Math.nextAfter( -Double.MAX_VALUE, -Infinity ) == -Infinity
assert Math.nextAfter( Infinity, 12d ) == Double.MAX_VALUE
assert Math.nextAfter( -Infinity, 12d ) == -Double.MAX_VALUE
assert Math.nextAfter( Zero, Infinity ) == Double.MIN_VALUE
assert Math.nextAfter( Infinity, Infinity ) == Infinity
assert Math.nextUp( 12.34d ) == Math.nextAfter( 12.34d, Infinity )
    //shortcut method for both doubles and floats

The result is NaN if the argument is NaN for ulp, sin, cos, tan, asin, acos, atan, exp, log, log10, sqrt, cbrt, IEEEremainder, ceil, floor, rint, atan2, abs, max, min, signum, sinh, cosh, tanh, expm1, log1p, nextAfter, and nextUp.
But not so with pow, round, hypot, copySign, getExponent, and scalb.

There's another math library called StrictMath that's a mirror of Math, with exactly the same methods. However, some methods (eg, sin, cos, tan, asin, acos, atan, exp, log, log10, cbrt, atan2, pow, sinh, cosh, tanh, hypot, expm1, and log1p) follow stricter IEEE rules about what values must be returned. For example, whereas the Math.copySign method usually treats some NaN arguments as positive and others as negative to allow greater performance, the StrictMath.copySign method requires all NaN sign arguments to be treated as positive values.