On Sun, 1 Mar 2015, Sven Schreiber wrote:
Am 01.03.2015 um 18:15 schrieb Alecos Papadopoulos:
> In practice these two numbers are not totally identical. For example I
> obtain
> 2.8841797876482436
> and
> 2.8841797876482445
>
> A roundabout way to deal with the problem does exist: multiply by some
> power of 10 representing desired precision in number of decimals, then
> truncate using the function "int", then apply "ranking".
>
> I was just wondering whether it would be worth the programming trouble
> to enhance directly the "ranking" function so as to "look" only
as deep
> as a user-specified number of decimals.
> The same added functionality could be given to the function "round",
> which currently only rounds to the nearest integer.
>
> It could be a useful feature of Gretl in general, since it would give
> the user the ability to specify what constitutes "equal" for his
> specific situation, without the need to use the roundabout trick
> described above.
>
I tend to agree that some way of defining "equal" in terms of
floating-point precision could be useful. Perhaps this could be
done by some 'set' option that would apply to all
equal-comparisons in gretl, instead of touching all the functions
separately. I wouldn't be surprised if somebody now points out
that this already exists...
We do have an internal macro, "floateq" which is used in some
contexts; it is defined via
#define floateq(x, y) (fabs((x) - (y)) < DBL_EPSILON)
That is, x and y are considered "equal" if the absolute value of
their difference is less than DBL_EPSILON, which is defined in the C
library header float.h. However (1) this is not user-configurable
(and I'm not sure it would be a good idea to make it so, in general)
and (2) DBL_EPSILON is a bit too small to do the job in the case
given above. (On my x86_64 machine DBL_EPSILON = 2.22045e-16.)
I think the best solution here might be a hansl function to "fix" a
vector of this sort, as in:
<hansl>
function void equalize_adjacent (matrix *m, scalar eps)
# assuming m is a column vector
scalar n = rows(m)
matrix s = msortby(m ~ seq(1,n)', 1)
loop i=2..n --quiet
if abs(s[i,1] - s[i-1,1]) < eps
s[i,1] = s[i-1,1]
endif
endloop
m = msortby(s, 2)[,1]
end function
# illustrative use
matrix m = {3, 2.8841797876482436, 2.8841797876482445, 1, 2}'
equalize_adjacent(&m, 1.0e-15)
printf "\n%.16f\n", m
</hansl>
Of course one could use the average of pairs of "adjacent" values
rather than just the smaller. And the function could be simpler if
one didn't care about preserving order.
Allin Cottrell