Unit in the last place
In computer science and numerical analysis, unit in the last place or unit of least precision (ULP) is the spacing between floating-point numbers, i.e., the value the least significant digit represents if it is 1. It is used as a measure of precision in numeric calculations. In radix b, if x has exponent E, then ULP(x) = machine epsilon · bE, but alternative definitions exist in the numerics and computing literature for ULP, exponent and machine epsilon, and they may give different equalities.
John Harrison uses a slightly different definition of ULP: ULP(x) is the distance between the two closest straddling floating-point numbers a and b (i.e., those with a ≤ x ≤ b and a ≠ b), assuming that the exponent range is not upper-bounded. These definitions differ only at signed powers of the radix.
The IEEE 754 specification—followed by all modern floating-point hardware—requires that the result of an elementary arithmetic operation (addition, subtraction, multiplication, division, and square root since 1985, and FMA since 2008) be within 0.5 ULP of the mathematically exact result, using John Harrison's definition—that is, that it be the best possible result. Reputable numeric libraries compute the basic transcendental functions to between 0.5 and about 1 ULP. Only a few libraries compute them within 0.5 ULP, this problem being complex due to the Table-Maker's Dilemma.
Let x be a nonnegative floating-point number and assume that the active rounding attribute is round to nearest. If ULP(x) is less than or equal to 1, then x + 1 > x. Otherwise, x + 1 = x. This is demonstrated in the following Haskell code typed at an interactive prompt:
> until (\x -> x == x+1) (+1) 0 :: Float 1.6777216e7 > it-1 1.6777215e7 > it+1 1.6777216e7
Here we start with 0 in 32-bit single-precision and repeatedly add 1 until the operation is idempotent. The result is equal to 224 since the significand for a single-precision number in this example contains 24 bits.
Another example, in Python, also typed at an interactive prompt, is:
>>> x = 1.0 >>> p = 0 >>> while x != x + 1: ... x = x * 2 ... p = p + 1 ... >>> x 9007199254740992.0 >>> p 53
In this case, we start with x = 1 and repeatedly double it until x = x + 1. The result is 253, because the double-precision floating-point format uses a 53-bit significand.
Since Java 1.5, the Java standard library has included
Math.ulp(float) functions. The C language library math.h provides the function nextafter to calculate the next double. The Boost C++ Libraries offer boost::math::float_distance(a, b) to calculate the floating point distance between two doubles.
- Higham, Nicholas (2002). Accuracy and Stability of Numerical Algorithms (2 ed). SIAM.
- Harrison, John. "A Machine-Checked Theory of Floating Point Arithmetic". Retrieved 17 July 2013.
- On the definition of ulp(x) by Jean-Michel Muller, INRIA Technical Report 5504 (accessed March 2012)