Unit in the last place

Source: Wikipedia, the free encyclopedia.

In

least significant digit (rightmost digit) represents if it is 1. It is used as a measure of accuracy in numeric calculations.[1]

Definition

The most common definition is: In radix with precision , if , then ,[2] where is the minimal exponent of the normal numbers. In particular, for normal numbers, and for subnormals.

Another definition, suggested by John Harrison, is slightly different: is the distance between the two closest straddling floating-point numbers and (i.e., satisfying and ), assuming that the exponent range is not upper-bounded.[3][4] These definitions differ only at signed powers of the radix.[2]

The

Table-maker's dilemma.[5]

Since the 2010s, advances in floating-point mathematics have allowed correctly rounded functions to be almost as fast in average as these earlier, less accurate functions. A correctly rounded function would also be fully reproducible. An earlier, intermediate milestone was the 0.501 ulp functions,[clarification needed] which theoretically would only produce one incorrect rounding out of 1000 random floating-point inputs.[6]

Examples

Example 1

Let be a positive floating-point number and assume that the active rounding mode is

round to nearest, ties to even
, denoted . If , then . Otherwise, or , depending on the value of the least significant digit and the exponent of . This is demonstrated in the following
Haskell code typed at an interactive prompt:[citation needed
]

> until (\x -> x == x+1) (+1) 0 :: Float
1.6777216e7
> it-1
1.6777215e7
> it+1
1.6777216e7

Here we start with 0 in single precision (binary32) and repeatedly add 1 until the operation does not change the value. Since the significand for a single-precision number contains 24 bits, the first integer that is not exactly representable is 224+1, and this value rounds to 224 in round to nearest, ties to even. Thus the result is equal to 224.

Example 2

The following example in Java approximates π as a floating point value by finding the two double values bracketing : .

// π with 20 decimal digits
BigDecimal π = new BigDecimal("3.14159265358979323846");

// truncate to a double floating point
double p0 = π.doubleValue();
// -> 3.141592653589793  (hex: 0x1.921fb54442d18p1)

// p0 is smaller than π, so find next number representable as double
double p1 = Math.nextUp(p0);
// -> 3.1415926535897936 (hex: 0x1.921fb54442d19p1)

Then is determined as .

// ulp(π) is the difference between p1 and p0
BigDecimal ulp = new BigDecimal(p1).subtract(new BigDecimal(p0));
// -> 4.44089209850062616169452667236328125E-16
// (this is precisely 2**(-51))

// same result when using the standard library function
double ulpMath = Math.ulp(p0);
// -> 4.440892098500626E-16 (hex: 0x1.0p-51)

Example 3

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
>>> x + 2 + 1
9007199254740996.0

In this case, we start with x = 1 and repeatedly double it until x = x + 1. Similarly to Example 1, the result is 253 because the

double-precision
floating-point format uses a 53-bit significand.

Language support

The

Boost C++ libraries
provides the functions boost::math::float_next, boost::math::float_prior, boost::math::nextafter and boost::math::float_advance to obtain nearby (and distant) floating-point values,[7] and boost::math::float_distance(a, b) to calculate the floating-point distance between two doubles.[8]

The C language library provides functions to calculate the next floating-point number in some given direction: nextafterf and nexttowardf for float, nextafter and nexttoward for double, nextafterl and nexttowardl for long double, declared in <math.h>. It also provides the macros FLT_EPSILON, DBL_EPSILON, LDBL_EPSILON, which represent the positive difference between 1.0 and the next greater representable number in the corresponding type (i.e. the ulp of one).[9]

The

Java standard library provides the functions Math.ulp(double) and Math.ulp(float)
. They were introduced with Java 1.5.

The Swift standard library provides access to the next floating-point number in some given direction via the instance properties nextDown and nextUp. It also provides the instance property ulp and the type property ulpOfOne (which corresponds to C macros like FLT_EPSILON[10]) for Swift's floating-point types.[11]

See also

References

  1. S2CID 222008826. Archived (PDF) from the original on 20 July 2006. Retrieved 20 January 2016. ([1], [2], [3]
    ).
  2. ^ .
  3. ^ Harrison, John. "A Machine-Checked Theory of Floating Point Arithmetic". Retrieved 17 July 2013.
  4. ^ Muller, Jean-Michel (2005–11). "On the definition of ulp(x)". INRIA Technical Report 5504. ACM Transactions on Mathematical Software, Vol. V, No. N, November 2005. Retrieved in 2012-03 from http://ljk.imag.fr/membres/Carine.Lucas/TPScilab/JMMuller/ulp-toms.pdf.
  5. ^ Kahan, William. "A Logarithm Too Clever by Half". Retrieved 14 November 2008.
  6. ^ Brisebarre, Nicolas; Hanrot, Guillaume; Muller, Jean-Michel; Zimmermann, Paul (May 2024). "Correctly-rounded evaluation of a function: why, how, and at what cost?".
  7. ^ Boost float_advance.
  8. ^ Boost float_distance.
  9. ^ ISO/IEC 9899:1999 specification (PDF). p. 237, §7.12.11.3 The nextafter functions and §7.12.11.4 The nexttoward functions.
  10. ^ "ulpOfOne - FloatingPoint | Apple Developer Documentation". Apple Inc. Apple Inc. Retrieved 18 August 2019.
  11. ^ "FloatingPoint - Swift Standard Library | Apple Developer Documentation". Apple Inc. Apple Inc. Retrieved 18 August 2019.

Bibliography