P is for Practical PerlMonks

### Re: check if 2 values are equal

by Corion (Pope)
 on Jan 24, 2006 at 18:52 UTC ( #525283=note: print w/replies, xml ) Need Help??

in reply to check if 2 values are equal

I think the three rules you want for equality are:

Two items are regarded as equal if

• they are both undef
• they are string-equal
• they are numerically equal

By translating these three rules into code, I come up with the following:

```sub equals {
my (\$val1,\$val2) = @_;
return (!defined \$val1 && !defined \$val2)
|| (\$val1 eq \$val2)
|| (\$val1 == \$val2)
};

But in such cases it really pays off if you write a test suite that tests your current implementation, then write your routine from scratch again with the rules you have found, and then test the new routine against the old test cases.

Replies are listed 'Best First'.
Re^2: check if 2 values are equal
by thedoe (Monk) on Jan 24, 2006 at 19:24 UTC

The problem with this is that the numeric comparison could return false positives. Try doing a comparison of 'aa' == 'bb'. With -w on, this does issue warnings, however it will still return true.

That is why something like Fletcher's looks_like_number from Scalar::Util is needed.

I have not used it myself, so I can not attest to the accuracy of this function, however the code would be like this:

```sub equals {
my (\$val1,\$val2) = @_;
return 1 if !defined \$val1 && !defined \$val2;
if (looks_like_number(\$val1) && looks_like_number(\$val2)) {
return \$val1 == \$val2;
} else {
return \$val1 eq \$val2;
}
}
Re^2: check if 2 values are equal
by eXile (Priest) on Jan 24, 2006 at 19:25 UTC
I agree my explanation of what I regard equal could be a little better. Your function doesn't work for me because I have to distinguish between an undef and a numeric 0 for instance (your function says these are equal).

I'll work out a testmatrix and manually check what i regard equal or not, thanks for that suggestion.

Re^2: check if 2 values are equal
by clinton (Priest) on Jan 24, 2006 at 19:31 UTC
I think you can do away with the third condition of (\$val1 == \$val2).

First, the eq should catch differences between numbers equally well as the ==. See Comparing values.

Secondly, the == would fail (under strict) if one of the values were a string.

For eq to work for numbers, you need to know that the values are being represented internally as numbers, for instance:

```  \$a = 1000;
\$b = 1e3;
print \$a eq \$b ? 1 : 0;
> 1
\$b = "1e3";
print \$a eq \$b ? 1 : 0;
> 0
\$b=\$b+0;
print \$a eq \$b ? 1 : 0;
> 1

My solution is wrong, but for different reasons. eq cannot replace ==:

```\$a = "01000";
\$b = 1000;

printf "\\$a eq \\$b : %s\n", \$a eq \$b;
printf "\\$a == \\$b : %s\n", \$a == \$b;

use strict; has no bearing on comparisons. What you are thinking of is use warnings;, which will warn about non-numeric values being compared with ==.

Re use warnings rather than use strict - thanks for the correction.

Likewise, you are right about the "0100" not being equal to 100, which is what I meant about being sure that the values are represented internally as numbers.

So if you said:

``` \$a = "01000";
\$b = 1000;
print \$a eq \$b ? 1 : 0;
> 0
\$a=\$a+0;
print \$a eq \$b ? 1 : 0;
> 1

I think you can do away with the third condition of (\$val1 == \$val2).

Tricky one. I thought the same at first.
But think of 0 and 0.0 or 0E0 - all numerically equal, but not sting equal.
Same goes for 1.1 and 1.10 and of course, there's more to think about.

Cheers, Sören

Re^2: check if 2 values are equal
by bart (Canon) on Jan 24, 2006 at 20:10 UTC
Your test function should return false if only one of the items is undef. You do not test for that.

Create A New User
Node Status?
node history
Node Type: note [id://525283]
help
Chatterbox?
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others musing on the Monastery: (8)
As of 2018-06-24 07:52 GMT
Sections?
Information?
Find Nodes?
Leftovers?
Voting Booth?
Should cpanminus be part of the standard Perl release?

Results (126 votes). Check out past polls.

Notices?