Unit in the last place
# Unit in the last place

Si definisce unit in the last place (unità in ultima posizione) o unit of least precision (unità di minore precisione), comunemente abbreviato in ulp, il valore assunto in un numero in virgola mobile dalla cifra unitaria in posizione meno significativa, ovvero la distanza fra due numeri macchina consecutivi. L'ulp è adatta come misura dei piccoli errori nelle operazioni atomiche, mentre si presta meno bene ad esprimere gli errori di computazioni più ampie, per cui è comunemente impiegata per esprimere gli errori nell'aritmetica dei calcolatori, meno spesso nell'analisi numerica.

## Definizione

Il concetto di ulp è stato introdotto da William Kahan nel 1960, e la definizione originale era la seguente:

    ulp(x) è la distanza fra i due numeri in virgola mobile più vicini a x, anche se x coincide con uno di essi.

Per tenere conto dell'introduzione di valori non numerici nella rappresentazione (come Inf e NaN), la definizione precedente è stata estesa imponendo di considerare solo i due numeri macchina più prossimi a x e finiti, e ponendo ulp(NaN) = NaN.

Una definizione proposta da John Harrison pone ulp(x) come la distanza fra due numeri macchina consecutivi in virgola mobile a e b tra i quali sia compreso x (ovvero a ≤ x ≤ b e a ≠ b), assumendo che l'intervallo dell'esponente non sia limitato superiormente.

Le definizioni di Kahan e Harrison coincidono quando applicate a numeri macchina, ma possono differire nel caso di numeri reali, per valori in prossimità di potenze della base. Ad esempio, in base 2 con p cifre, se 1 < x < 1 + $2^{-p-1}$ si ha ${\text{ulp}}_{\text{Kahan}}(x)=2^{-p}$ e ${\text{ulp}}_{\text{Harrison}}(x)=2^{-p+1}$.

David Goldberg non definisce ulp come una funzione, ma come la quantità espressa dalla cifra meno significativa unitaria del numero macchina, da cui si ricava una funzione che ad un numero in virgola mobile con p cifre x ∈ $[b^e,$ $b^{e+1}]$ associa il valore ${\text{ulp}}(x)=b^{e-p+1}$.

## Proprietà

Quando si arrotonda un numero in una rappresentazione in virgola mobile, il valore esatto può differire per difetto o per eccesso fino ad un mezzo del valore della cifra meno significativa nella rappresentazione macchina, per cui si ha un errore assoluto limitato fino a ±0,5 ulp. Considerando un numero in base b con p cifre ed esponente e, nella forma d,d...d × $b^e,$ il valore del numero varia fra $b^e$ e $b×b^e,$ per cui l'errore relativo r associato a 0.5 ulp è compreso tra

    ${\frac {{\frac {b}{2}}\cdot b^{-p}}{b^{e+1}}}\times b^{e}\leq r\left({\tfrac {1}{2}}{\text{ulp}}\right)\leq {\frac {{\frac {b}{2}}\cdot b^{-p}}{b^{e}}}\times b^{e}$

ovvero

    ${\tfrac {1}{2}}\times b^{-p}\leq r\left({\tfrac {1}{2}}{\text{ulp}}\right)\leq {\tfrac {b}{2}}\times b^{-p}$

Si osserva quindi che l'errore relativo corrispondente a 0,5 ulp può variare di un fattore (detto wobble) pari a b. Quando si arrotonda un numero reale con un numero macchina, l'errore relativo è sempre limitato dall'estremo superiore del precedente intervallo, che viene definito come epsilon di macchina.

Lo standard IEEE 754, implementato da praticamente tutto l'hardware in virgola mobile moderno, richiede che i risultati delle operazioni elementari in virgola mobile (addizione, sottrazione, moltiplicazione, divisione, modulo e radice quadrata dal 1985, e fma dal 2008) siano correttamente arrotondati, quindi con un errore limitato a 0,5 ulp. Nel caso delle funzioni trascendenti in generale non è semplice determinare il numero di cifre necessarie nel calcolo per garantire un arrotondamento esatto (problema noto come table-maker's dilemma), e non tutte le librerie numeriche garantiscono l'arrotondamento delle funzioni trascendenti con precisione di 0,5 ulp, ma solitamente hanno almeno la precisione di 1 ulp.

## Supporto nei linguaggi di programmazione

Il linguaggio C definisce nella standard library (header <math.h>) delle funzioni per calcolare il precedente e successivo numero macchina per i numeri in virgola mobile: nextafterf e nexttowardf per variabili float, nextafter e nexttoward per variabili double, nextafterl e nexttowardl per variabili long double.

Le librerie Boost forniscono le funzioni boost::math::float_next, boost::math::float_prior, boost::math::nextafter and boost::math::float_advance per determinare i numeri in virgola mobile precedenti e successivi, e boost::math::float_distance(a, b) per calcolare la distanza tra due numeri in virgola mobile.

In Ada i numeri macchina immediatamente precedente e successivo di un valore in virgola mobile possono essere ottenuti con gli attributi 'Pred e 'Succ, ad esempio per una variabile X di tipo Float tali valori sono dati da Float'Pred(X) e Float'Succ(X).

La libreria standard Java include dalla versione 1.5 le funzioni Math.ulp(double) e Math.ulp(float), che permettono di calcolare direttamente il valore ulp di una variabile.

