sigfigwould be the one you outlined (though you would need to take negative values and zero into account when taking the log, of course).
This is definitely the mathematicians approach, but I think there is an easier way, which lets perl do most of the work. If
$n is the number of required digits, then compare
my $format = "%."+($n-1)+"E"; sprintf($format,$a) eq sprintf($format,$b);This asks perl to format the numbers using exponential form with n-1 decimal digits (and one leading digit, so n total digits). This avoids the numeric issues, the issues of negatives, and so forth.
In terms of the percentages, I think this is a special case that should be handled as a separate class (say a subclass of Real) rather than as part of the core. I don't see this as generally applicable (e.g., in comparing the endpoints of intervals, or the real and imaginary parts of complex numbers, both of which are places where the
tolerance values are used). I could see this as a special probability or percentage class, though.