This page is in progress and is the artifact for

Numbers and Math

As of version 1.3, Clojure provides full support for JVM primitive values, making it possible to write high performance, idiomatic Clojure code for numeric applications.

Numeric Types


It is possible to create most types of numbers as literals directly within Clojure code:


Literal Syntax


primitive long (decimal)

a number, with no leading zeroes


primitive long (octal)

a number with a leading zero


primitive long (hexadecimal)

a number prefixed by 0x


primitive long (arbitrary base)

base + r + the number

2r101010, 12r36

primitive double (standard notation)

a number containing a decimal point

98.8, 3.3

primitive double (scientific notation)

coefficient + E + sign (optional) + exponent

6.0221479E+23, 6.67428E-11

rational number

number including a slash, with no spaces

1/3, 33/16

fixed point decimal (java.lang.BigDecimal)

number with M suffix


big integer (clojure.lang.BigInt)

number with N suffix, or a number too large to fit in a long

42N, 42000000000000000000

Math Operations

All of Clojure's mathematical functions and operators work polymorphically on all numeric types, primitive or boxed. When given primitives, they will use native JVM operations if possible.

When different types of numbers are used in a math operation, the result will be the larger or more general of the two types. For example, an operation involving a primitive long and a primitive double will result in a primitive double, and an operation between a primitive long and a BigInt will result in a BigInt. On other words, doubles and BigInts are "contagious" across operations. This is an intentional and useful feature, as it allows entire algorithms to be fully polymorphic based on their inputs. An algorithm written using standard operators will use fast native integer math when given primitive longs, fast native floating point math when given doubles, and will function correctly with no overflow when a BigInt is introduced.

When a primitive integer operation results in a value that too large to be contained in a primitive value, a java.lang.ArithmeticException is thrown - values will never roll over silently. This feature allows primitive math to be very fast, while retaining safety from bugs due to silent overflow. It also ensures consistent semantics across usage with both primitives and boxed numbers.

If automatic upgrade to a BigInt is required, and introducing a BigInt to the original operation to make use of BigInt contagion is not possible, Clojure provides a set of alternative math operators suffixed with an apostrophe: +', -', *', inc', and dec'. These operators auto-promote to BigInt upon overflow, but are less efficient than the regular math operators in that they cannot return primitive integers, only boxed ones.

For applications where integer overflow is not a concern, additional performance may be achieved by using the provided unchecked operations: unchecked-add, unchecked-subtract, unchecked-multiply, unchecked-divide, unchecked-inc, unchecked-dec, unchecked-negate and unchecked-remainder. Using these operators removes the slight overhead associated with bounds checking, but is unsafe in that primitive types will silently roll over when they exceed the size allowed by their bit length, instead of throwing an exception as the standard operators do.


The = operator (equality) tests numeric equality. It compares values in a type-independent manner, but not between different categories of numbers (e.g, floating point types and integer types.) This allows numbers to be used as map keys with correct semantics. To check numerical equivalence between numbers of different categories, use the == (equivalence) operator.

Primitive Hinting

By default, when a number is passed to or returned from a Clojure function, it is boxed (that is, it is handled as a java.lang.Object). To prevent this, it is possible to add primitive type hints to a Clojure function. The return type can be hinted as a primitive by placing ^double or ^long immediately before the argument vector, and argument types by placing the hints immediately before each argument.

For example, the following function uses only primitive longs with no boxing, even across its recursive function call boundary:

(defn fib ^long [^long n]
    (if (<= n 1)
        (+ (fib (dec n)) (fib (- n 2)))))

It is important to note that due to the underlying Java implementation, functions which take primitive arguments may only have 4 or fewer arguments. Trying to define a function with primitive hints and more than four arguments will result in a compiler exception.

Casting and Coercions

It is possible to convert a boxed number into a JVM primitive using one of the following coercion functions: byte, char, int, long, float or double.

Similarly, it is possible to convert a primitive number into its boxed form using the num function, or into a BigDecimal or BigInt using the bigdec or bigint functions, respectively.