跳至內容

最後一位上的單位值

維基百科,自由的百科全書

計算機科學數值分析中,最後一位上的單位值或稱最小精度單位,縮寫為ULP,是毗鄰的浮點數值之間的距離,也即浮點數在保持指數部分的時候最低有效數字為1所對應的值。ULP用於度量數值計算的精度。[1]

例如:圓周率位於毗鄰的雙精度浮點數3.1415926535897927與3.1415926535897936之間。

定義[編輯]

底數b,如果x的指數為E,那麼ULP(x) = 機器精度·bE[2]但在計算機與數值計算的文獻中,對ULP指數機器精度也可用其它方式定義。如John Harrison給出的定義: ULP(x)是兩個最近的跨(straddlingx的浮點數ab的距離,即axbab,並且在指數無上限的情形。[3][4]這兩個定義基本等價。

被所有現代浮點硬體遵從IEEE 754標準要求基本算術運算(1985年起的加法、減法、乘法、除法、求平方根,以及2008年起的「積和熔加運算(FMA)」)的結果近似到最近的浮點數且與數學確切結果的距離在0.5 ULP範圍內。這性質意味著近似結果與數學確切結果的距離是最小的(但對於居中情形,有兩個毗鄰的浮點數都滿足上述要求)。有美譽的數值庫(numeric library)計算基本超越函數的誤差在0.5至大約1 ULP間。僅有少數庫在計算超越函數時的誤差小於0.5 ULP,這一問題相當複雜,歸因於Table-Maker's Dilemma英語Table-maker's dilemma[5]

例子[編輯]

找到最接近圓周率的雙精度浮點數:

#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)
*/

xIEEE 754表示時四捨五入且捨入到偶數的操作記為RN。如果ULP(x)的值小於等於1,那麼RN(x + 1) > x;否則,RN(x + 1) = xRN(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
... 
>>> x
9007199254740992.0
>>> p
53
>>> x + 2 + 1
9007199254740996.0

這個例子中,從x = 1開始,反覆地翻倍直至x = x + 1。結果是253,因為雙精度浮點數格式使用了53位有效數字,從而ulp(253)=253*2-52=2 > 1 。即,在這裡雙精度浮點數可表示的最小精度間隔已經是2了。

語言支持[編輯]

從Java 1.5, Java語言的標準庫包含了函數: Math.ulp(double)Math.ulp(float)

C語言標準庫從C99開始提供了計算給定方向的下一個浮點數的函數: nextafterfnexttowardf用於float, nextafternexttoward用於double, nextafterlnexttowardl用於long double, 都在<math.h>中聲明。[6]

Boost C++ Libraries提供了boost::math::float_next, boost::math::float_prior, boost::math::nextafterboost::math::float_advance等函數獲取鄰近的浮點數。 [7]boost::math::float_distance(a, b)計算兩個double值之間的浮點距離。 [8]

參見[編輯]

參考文獻[編輯]

  1. ^ David Goldberg: What Every Computer Scientist Should Know About Floating-Point Arithmetic, section 1.2 Relative Error and Ulps, ACM Computing Surveys, Vol 23, No 1, pp.8, March 1991.
  2. ^ Higham, Nicholas. Accuracy and Stability of Numerical Algorithms (2 ed). SIAM. 2002. 
  3. ^ Harrison, John. A Machine-Checked Theory of Floating Point Arithmetic. [2013-07-17]. (原始內容存檔於2021-02-24). 
  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. [2008-11-14]. (原始內容存檔於2015-07-27). 
  6. ^ ISO/IEC 9899:1999 specification (PDF). . p. 237, §7.12.11.3 The nextafter functions and §7.12.11.4 The nexttoward functions [2016-04-08]. (原始內容存檔 (PDF)於2018-01-11). 
  7. ^ Boost float_advance. 
  8. ^ Boost float_distance.