[sf-perl] Comparing structures, ignoring floating point roundoff differences

Garth Webb garth at perijove.com
Mon Nov 21 23:19:23 PST 2005


How about:


use strict;

use constant TOLERANCE => 0.01;

sub is_equal {
    my ($v1, $v2) = @_;

    return unless ref $v1 eq ref $v2;

    if (ref $v1 eq 'HASH') {
        return hash_eq($v1, $v2);
    } elsif (ref $v2 eq 'ARRAY') {
        return array_eq($v1, $v2);
    } elsif (not ref $v1) {
        return scalar_eq($v1, $v2);
    } else {
        return;
    }
}

sub hash_eq {
    my ($h1, $h2) = @_;

    foreach my $k (keys %$h1) {
        return unless is_equal($h1->{$k}, $h2->{$k});
    }

    return 1;
}

sub array_eq {
    my ($a1, $a2) = @_;

    foreach my $i (0..$#$a1) {
        return unless is_equal($a1->[$i], $a2->[$i]);
    }

    return 1;
}

sub scalar_eq {
    my ($s1, $s2) = @_;

    return $s1 =~ /[0-9\.]+/ ? abs($s1 - $s2) < TOLERANCE : $s1 eq $s2;
}


On Mon, 2005-11-21 at 11:35 -0800, Joseph Brenner wrote:
> I've got a problem where I need to compare structures that have
> floating point numbers stashed in them.  I want to test the
> structures for identity (ala is_deeply from Test::More), but
> ignore tiny differences in the floating point numbers.  
> 
> This seems like something that ought to be a solved problem by
> now, but I'm having trouble finding it.  I had some hopes for 
> Test::Deep, which at least has a "num" comparison operation where 
> you can set a tolerance to ignore, but it looks to me like that's 
> only for comparing a computed value to an expected constant
> value: I need to compare computed values that are expected to
> match each other. 
> 
> Does that ring any bells with anyone? 
> _______________________________________________
> SanFrancisco-pm mailing list
> SanFrancisco-pm at pm.org
> http://mail.pm.org/mailman/listinfo/sanfrancisco-pm



More information about the SanFrancisco-pm mailing list