This cookbook covers working with mathematics in Clojure, using built-in functions, contrib libraries, and parts of the JDK via interoperability.

This work is licensed under a Creative Commons Attribution 3.0 Unported License (including images & stylesheets). The source is available on Github.

Preliminaries

This cookbook covers Clojure 1.11 (or later) and the clojure.math namespace introduced in that release.

It's assumed that either you have the following in your source code's ns macro:

(:require [clojure.math :as math])

or else in the repl you've loaded it like so:

(require '[clojure.math :as math])

Recipes

Boxed and Unboxed Math

This section is adapted from Alex Miller's "Inside Clojure" blog post on boxed math warnings.

By default, Clojure treats numbers as either java.lang.Long or java.lang.Double -- known as "boxed numbers" -- rather than the underlying primitives long and double. Values are passed around as java.lang.Object. In performance-sensitive code, you may want to use the primitive types directly and Clojure supports type hints for this purpose.

(defn sum-squares [a b]
  (+ (* a a) (* b b)))

In this function, both a and b are java.lang.Object and when you call (sum-squares 3 4) both 3 and 4 are boxed (as java.lang.Long) and the math is compiled into a sequence of calls to methods in clojure.lang.Numbers that accept java.lang.Object arguments.

We can improve efficiency by using type hints for both the arguments and the return type:

(defn sum-squares ^long [^long a ^long b]
  (+ (* a a) (* b b)))

This lets Clojure produce a more efficient version of the function that accepts primitive arguments and produces a primitive result.

A useful Var in this context is *unchecked-math* which controls whether the compiler will generate checked or unchecked math operations. It can also warn you about boxed math operations.

user=> (set! *unchecked-math* :warn-on-boxed)
:warn-on-boxed
user=> (def x 3)
#'user/x
user=> (def y 4)
#'user/y
user=> (* x y)
Boxed math warning, NO_SOURCE_PATH:1:1 - call: public static java.lang.Number clojure.lang.Numbers.unchecked_multiply(java.lang.Object,java.lang.Object).
12

You can also set *unchecked-math* to true, which will cause the compiler to generate primitive math operations, if it can, without checking for overflow.

Simple Math

clojure.core provides a number of basic math operations as functions:

(+ 3 4)    ;=> 7
(- 3 4)    ;=> -1
(* 3 4)    ;=> 12
(/ 3 4)    ;=> 3/4  (an exact ratio)
(/ 3.0 4)  ;=> 0.75
(double (/ 3 4)) ;=> 0.75 (convert a ratio to a double)

(inc 5)    ;=> 6
(dec 5)    ;=> 4

For doing integer division and getting remainders (modulus), see the docs for quot, rem, and mod, which are all provided in clojure.core.

abs, min, and max are also provided in clojure.core and are optimized for both long and double primitive types, as well as working with boxed numbers.

For exponents, square roots, rounding, ceiling, floor, etc, see the clojure.math namespace:

(math/pow 2 3)   ;=> 8.0
(math/sqrt 9)    ;=> 3.0
(math/round 3.4) ;=> 3
(math/round 3.6) ;=> 4
(math/ceil 3.4)  ;=> 4.0
(math/floor 3.6) ;=> 3.0

Prior to Clojure 1.11, you could use the Java platform's java.lang.Math class for these operations, e.g., (Math/pow 2 3).

Trigonometry

Use what clojure.math provides, for example:

math/PI       ;=> 3.14159...
(math/sin x)
(math/cos x)
(math/tan x)

As with Simple Math above, prior to Clojure 1.11, you could use the Java platform's java.lang.Math class for these operations, e.g., (Math/sin x).

Combinatorics

For combinatoric functions (such as combinations and permutations), see the math.combinatorics contrib library.