SQLite Forum

Decimal128
Login
Well, those two computational results happen to be exactly equal.  That is, the distance between them is 0 ulp (zero Units in the Last Place).

```
sqlite> select ulps(1234567890.3, 1234567890.1 + 0.2);
┌────────────────────────────────────────┐
│ ulps(1234567890.3, 1234567890.1 + 0.2) │
├────────────────────────────────────────┤
│ 0.0                                    │
└────────────────────────────────────────┘
```

The value of the "error instilled by a unit in the last place" is:

```
sqlite> select ulp(1234567890.3);
┌──────────────────────┐
│  ulp(1234567890.3)   │
├──────────────────────┤
│ 2.38418579101563e-07 │
└──────────────────────┘
```

I calculate the ULP as,

```
/*
 * Compute the ULP Error for floating point numbers of scale value
 * with significand bits in the significand
 */

static __inline double ulp(double value, int significand)
{
    int exponent;
    double mantissa = frexp(value, &exponent);
    return ldexp(1.0, exponent - significand);
}
```

The "epsilon" can be calculated as:

```
def epsilon(x):
    x = abs(x)
    e = x
    while (x + e) != x:
        e /= 2.0
    return e * 2.0
```

which will return the "minimum increment" to the next representable number in terms of the number provided -- that is, the smallest number which when added to x does not still result in x -- this does not work for 0.

The "epsilon" of 1234567890.3 is:

```
>>> epsilon(1234567890.3)
1.3706456972739644e-07
```

Note that the ULP and the Epsilon are not the same.  The ULP, in theory, returns the "distance" between the next smaller representable number and the next larger representable number.  The epsilon return the minimum power-of-2 which when added to x gives a different result than x.