Beefy Boxes and Bandwidth Generously Provided by pair Networks
more useful options
 
PerlMonks  

comparison with bitwise operators

by alextor (Novice)
on Jan 13, 2011 at 20:18 UTC ( #882228=perlquestion: print w/ replies, xml ) Need Help??
alextor has asked for the wisdom of the Perl Monks concerning the following question:

I'm trying to compare a value to two numbers like this:
if( $var == 2 || $var == 3){ .. do stuff .. }
and I was wondering whether there's a way to shorten the comparison to something like if($var == (2 || 3)), which I've tried and it doesn't work. thanks

Comment on comparison with bitwise operators
Select or Download Code
Re: comparison with bitwise operators
by toolic (Chancellor) on Jan 13, 2011 at 20:26 UTC
    I can think of 3 ways:
    use warnings; use strict; use List::MoreUtils qw (any); my $var = 3; if (grep { $var == $_ } 2, 3) { print "in list\n"; } else { print "not in list\n"; } if (any { $var == $_ } 2, 3) { print "in list\n"; } else { print "not in list\n"; } my %vals = map {$_ => 1} 2, 3; if (exists $vals{$var}) { print "in list\n"; } else { print "not in list\n"; } __END__ in list in list in list
    Update: a 4th way involves the smart match operator
    use 5.010; if ($var ~~ [2, 3]) { print "in list\n"; } else { print "not in list\n"; }
      thanks!
      > my %vals = map {$_ => 1} 2, 3;
      > if (exists $vals{$var}) {
      >     print "in list\n";
      > }

      if you wanna test with exists hash-slices are shorter! :)

      my %vals; @vals{2,3}=();

      but need a separate step for declaration! :(

      UPDATE: why do you check with exists anyway?

      Cheers Rolf

        why do you check with exists anyway?
        Out of habit. I consider it defensive programming. In this small example, there is no need to use exists because I have clearly set the values of all keys to 1, which is defined and true, as opposed to undef or 0.

        I also kinda like how it reads.

        If you can convince me there is a significant penalty (performance/memory/etc.) for using exists, then I may consider changing my habit.

Re: comparison with bitwise operators
by kennethk (Monsignor) on Jan 13, 2011 at 20:26 UTC
    If you mean you want to test if the 2's place is set, you can use bitwise operators (see Bitwise And and Bitwise Or and Exclusive Or in perlop). Something like

    #!/usr/bin/perl use strict; use warnings; for my $value (1, 2, 3, 4, 5, 6, 7, 8) { print "$value: "; if ($value & 0x2) { print "yes\n"; } else { print "no\n"; } }

    This was recently discussed in Bit operation.

Re: comparison with bitwise operators
by ikegami (Pope) on Jan 13, 2011 at 20:41 UTC
      Careful, there are subtle differences!

      Which comparison operator ~~ internally choses, depends on the type of the variable:

      DB<1> $a="2.0" DB<2> p [2,3] ~~ $a DB<3> p $a == 2 1 DB<4> p [2,3] ~~ $a 1

      BTW: line 4 demonstrates one of the weirdest side effects of perl's auto-casting ...

      Cheers Rolf

        That's not the code I posted. The code I posted does not suffer from the problem you describe.

        >perl -E"$a='2.0'; say $a~~[2,3];" 1 >perl -E"$a=2; say $a~~[2,3];" 1
        this is a misplaced reply to 882287

        > That's not the code I posted. The code I posted does not suffer from the problem you describe.

        hmm I checked your code...

        :~$ perl -E '$a="2.0"; say [2,3] ~~ $a;' :~$ perl -E '$a="2.0"; say $a~~[2,3];'

        But not the version...I'm using 5.10.0 and not 5.10.1!

        And the line It is always commutative, i.e. "$a ~~ $b" behaves the same as "$b ~~ $a".

        has been erased from newer docs (see Smart matching in detail)...

        Anyway smartmatch is still too magic for my taste!

        Cheers Rolf

Re: comparison with bitwise operators
by moritz (Cardinal) on Jan 13, 2011 at 20:47 UTC
Re: comparison with bitwise operators
by Anonyrnous Monk (Hermit) on Jan 13, 2011 at 21:30 UTC
    if($var == (2 || 3))

    Several solutions have already been offered, so I'd just like to elaborate on why your attempt didn't work.

    Actually, || is not a bitwise operator (as you say in the title), but a logical operator, treating the individual parts in their entirety as boolean values (true/false).  I.e., since both 2 and 3 are true, 2 || 3 is true as well, and that's what you're comparing $var against. More precisely, you're comparing $var to 2, because the first true value is "returned" as is.

    The respective bitwise operator would be |, which combines the corresponding individual bits of the values, i.e. 2 | 3 == 3, or 0b10 | 0b11 == 0b11.  In other words, if($var == (2 | 3)) wouldn't work either for combining the tests the way you're thinking of, because if $var is 2, you'd compare it against 3, which is false, of course.

      Thanks for the explanation!
Re: comparison with bitwise operators (sarcasm)
by tye (Cardinal) on Jan 13, 2011 at 21:32 UTC
    if( 3-2 == abs( 3+2 - 2*$var ) ) { # q-: }

    If you have 3 values, it takes slightly more work:

    if( not $var**3 - 12*$var**2 + 41*$var - 42 ) { # $var is 2, 3, or 7 }

    For the specific case of 2 and 3:

    if( 3 == ( $var | 1 ) ) {

    - tye        

      That reminds me of the time I had to debug this old BASIC game that used hundreds of expressions like

      y = 4 - (x > 3) * 2

      to achieve

      $y = $x > 3 ? 6 : 4;

      Some assignments even had more than one such conditional per line. It was hell.

      (True was -1)

Re: comparison with bitwise operators
by Marshall (Prior) on Jan 13, 2011 at 22:51 UTC
    Your code as written is very clear and will also run very fast. A fewer number of characters in the source code does not necessarily translate into more efficient run-time code. Clarity should be a major objective of code.

    In short, what you have written is fine and I would leave it that way.

      When checking against just two values you are certainly right, but for more values the other approaches scale better.

      Cheers Rolf

        I think we are in agreement.
        I was keying on the OP's statement of the problem: "compare a value to two numbers".
        The proposed formulation is very, very good! I see no reason to "improve" it.

        For efficiency, with a much larger set of possibilities, "does value X exist within a data set?", I would think that the List::MoreUtils qw (any); solution is the best for two reasons:
        a)Since it is an XS module it will run faster than native Perl code,
        b)the grep solution will examine all possibilities in order to return the scalar result of number of "matches" whereas a well written XS module would return true immediately upon the first match.

        The Perl "or" code will also "give up" and stop processing immediately upon the first successful match (OR condition is satisfied). I think this is just fine for say 1/2 dozen "or" conditions. Of course the expected probability of returning "true" should be taken into account in the ordering of an "if" statement. This may result in faster code than using say the "smart match" operator in Perl 5.10. Benchmark the program if there is any doubt.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://882228]
Approved by Mr. Muskrat
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others rifling through the Monastery: (12)
As of 2014-12-18 20:56 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    Is guessing a good strategy for surviving in the IT business?





    Results (62 votes), past polls