最后一位上的单位值

在计算机科学与数值分析中，最后一位上的单位值或称最小精度单位，缩写为ULP，是毗邻的浮点数值之间的距离，也即浮点数在保持指数部分的时候最低有效数字为1所对应的值。ULP用于度量数值计算的精度。
例如：圆周率位于毗邻的双精度浮点数3.1415926535897927与3.1415926535897936之间。

定义

设底数为b，如果x的指数为E，那么ULP(x) = 机器精度·bᴱ。但在计算机与数值计算的文献中，对ULP，指数与机器精度也可用其它方式定义。如John Harrison给出的定义: ULP(x)是两个最近的跨（straddling）x的浮点数a与b的距离，即a ≤ x ≤ b且a ≠ b，并且在指数无上限的情形。这两个定义基本等价。
被所有现代浮点硬件遵从IEEE 754标准要求基本算术运算（1985年起的加法、减法、乘法、除法、求平方根，以及2008年起的“积和熔加运算（FMA）”）的结果近似到最近的浮点数且与数学确切结果的距离在0.5 ULP范围内。这性质意味着近似结果与数学确切结果的距离是最小的（但对于居中情形，有两个毗邻的浮点数都满足上述要求）。有美誉的数值库（numeric library）计算基本超越函数的误差在0.5至大约1 ULP间。仅有少数库在计算超越函数时的误差小于0.5 ULP，这一问题相当复杂，归因于Table-Maker's Dilemma。

例子

找到最接近圆周率的双精度浮点数：
#include <cmath> #include <cstdio> #define PI 3.14159265358979323846264338327950288419716939937510582097494459230 int main() 
{
    printf("%.17g (%a)\n", PI, PI); 
    printf("%.17g (%a)\n", std::nextafter(PI, 0.0), std::nextafter(PI, 0.0)); 
    printf("%.17g (%a)\n", std::nextafter(PI, 4.0), std::nextafter(PI, 4.0)); 
}/* Output:3.1415926535897931 (0x1.921fb54442d18p+1)3.1415926535897927 (0x1.921fb54442d17p+1)3.1415926535897936 (0x1.921fb54442d19p+1)*/
设x用IEEE 754表示时四舍五入且舍入到偶数的操作记为RN。如果ULP(x)的值小于等于1，那么RN(x + 1) > x；否则，RN(x + 1) = x或RN(x + 1) = x + ULP(x)，取决于最低有效位（least significant digit）与x的指数部分。下面的Python程序展示了这个例子：
>>> x = 1.0>>> p = 0>>> while x != x + 1:...   x = x * 2...   p = p + 1... >>> x9007199254740992.0>>> p53>>> x + 2 + 19007199254740996.0
这个例子中，从x = 1开始，反复地翻倍直至x = x + 1。结果是2⁵³，因为双精度浮点数格式使用了53位有效数字，从而ulp(2⁵³)=2⁵³*2⁻⁵²=2 > 1 。即，在这里双精度浮点数可表示的最小精度间隔已经是2了。

语言支持

从Java 1.5, Java语言的标准库包含了函数： Math.ulp(double)与 Math.ulp(float)。
C语言标准库从C99开始提供了计算给定方向的下一个浮点数的函数： nextafterf与nexttowardf用于float, nextafter与nexttoward用于double, nextafterl与nexttowardl用于long double, 都在<math.h>中声明。
Boost C++ Libraries提供了boost::math::float_next, boost::math::float_prior, boost::math::nextafter与boost::math::float_advance等函数获取邻近的浮点数。 。boost::math::float_distance(a, b)计算两个double值之间的浮点距离。