Beefy Boxes and Bandwidth Generously Provided by pair Networks
P is for Practical
 
PerlMonks  

Determining whether a value is zero.

by JavaFan (Canon)
on Mar 10, 2011 at 11:51 UTC ( [id://892390]=perlmeditation: print w/replies, xml ) Need Help??

Sounds like an easy question, doesn't it? But let's make it a challenge. Write a subroutine, accepting a single argument, and using pure Perl only, return true if its argument is zero, false otherwise.

Here are a few arguments that should result in true being returned:

$x = 0; $x = "0"; $x = 0.0; $x = Scalar::Util::dualvar 0, 1;
But it should return false on the following:
$x = 1; $x = "foo"; $x = "00"; $x = "0 "; $x = undef; $x = ""; $x = Scalar::Util::dualvar 1, 0; $x = "0.0";

Replies are listed 'Best First'.
Re: Determining whether a value is zero.
by BrowserUk (Patriarch) on Mar 10, 2011 at 13:28 UTC

    I don't suppose that you would entertain any argument with your arbitrary definition of what constitutes zero?

    Any definition that deems "0" as zero, but "00", "0.0" & "0 " as not, is so arbitrary as to render the challenge pointless.


    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.

      It may be pointless from the sense of practical application. I found it interesting as a way of familiarizing the various representations of zero, and how the various operators treat a scalar (dual-)variable in Perl.

        I'm not adverse to a purely intellectual challenge.

        But the specification of what is and what is not zero doesn't seem to comply with any either real-world or rational definition that I can think of. I cannot think of any existing implementation that would interprete "0" as zero, and not "00" or "0 ". Nor can I see any rational for doing so.

        Without some logic as to why these arbitrary rules have been picked, you might as well do:

        #! perl -slw use strict; use feature qw[ state ]; use Scalar::Util qw[ dualvar ]; my @true = ( 0, "0", 0.0, Scalar::Util::dualvar( 0, 1 ) ); my @false = ( 1, "foo", "00", "0 ", undef, "", Scalar::Util::dualvar( 1, 0 ), "0.0" ); sub isZero { state %isZero; unless( %isZero ) { $isZero{ $_ } = 1 for @true; $isZero{ $_ } = 0 for @false; } return $isZero{ $_ } if exists $isZero{ $_ }; die "Don't know"; } print "$_ : ", isZero( $_ ) for @true; print "$_ : ", isZero( $_ ) for @false;

        As it can be infinitely extended to deal with any set of illogical rules.


        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.
      There is one point, in "0.0"
      Any definition that deems "0" as zero, but "00", "0.0" & "0 " as not, is so arbitrary
      Please, take that up with Larry Wall. It isn't my fault that he considered "0" to be false, but "00", "0.0" & "0 " to be true. But then, that guy is well known for his arbitrary decisions which he never entertains any argument with, rendering the entire Perl language pointless.
        he considered "0" to be false,

        That's not quite the same things as considering '00' to be non-zero is it!

        C:\test>perl -e"print '00' == 0" 1

        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.
        Certainly is interesting that quoted 00 is true while quoted 0 is false (but it sounds like '0', "0" are special cases).
        perl -E 'say 0 ? q{true} : q{false}' # false perl -E 'say 00 ? q{true} : q{false}' # false perl -E 'say q{0} ? q{true} : q{false}' # false perl -E 'say qq{0} ? q{true} : q{false}' # false perl -E 'say q{00} ? q{true} : q{false}' # true perl -E 'say qq{00} ? q{true} : q{false}' # true
        Perl 5.10.1 on Solaris 10 SPARC.

        Elda Taluta; Sarks Sark; Ark Arks

Re: Determining whether a value is zero.
by choroba (Cardinal) on Mar 10, 2011 at 12:30 UTC
      Close, but it reports dualvar (0, "0 ") not to be a zero.
        You only defined the expected values for
        Scalar::Util::dualvar 0, 1; Scalar::Util::dualvar 1, 0;
        So the effect you mentioned seems to be a specification-issue ;-)
        I give up. I cannot tell dualvar 0,"0 " from "0 ":
        use Devel::Peek; use Scalar::Util qw/dualvar/; my @x = ("0 ",dualvar(0,"0 ")); (10.2+$_).$_ for @x; Dump $x[0]; Dump $x[1];
        gives
        SV = PVNV(0x830ef78) at 0x8310564 REFCNT = 1 FLAGS = (IOK,NOK,POK,pIOK,pNOK,pPOK) IV = 0 NV = 0 PV = 0x835465c "0 "\0 CUR = 2 LEN = 4 SV = PVNV(0x830ef8c) at 0x8310584 REFCNT = 1 FLAGS = (IOK,NOK,POK,pIOK,pNOK,pPOK) IV = 0 NV = 0 PV = 0x833b77c "0 "\0 CUR = 2 LEN = 4
Re: Determining whether a value is zero.
by ikegami (Patriarch) on Mar 11, 2011 at 05:04 UTC
    use B qw( svref_2object SVf_IOK SVf_NOK SVf_POK ); sub is_zero { my $sv = svref_2object(my $ref = \$_[0]); my $flags = $sv->FLAGS; return $sv->IVX == 0 if $flags & SVf_IOK; return $sv->NVX == 0 if $flags & SVf_NOK; return $sv->PV eq "0" if $flags & SVf_POK; return 0; }
      Give that man a cigar (or another vice to his liking). Not only did ikegami understood and solved the challenge, he didn't feel the need to argue the rules weren't to his liking.

      If there's a way to do it without having to break encapsulation of value and peek at their internal flags, I don't know such a way - but I'd love to hear about it.

        If there's a way to do it without having to break encapsulation of value and peek at their internal flags, I don't know such a way - but I'd love to hear about it.

        Tried and failed. Need to find something that can distinguish between absent IV and NV and zero IV or NV. This boils down to finding something that

        • favours IV and NV over PV, and
        • doesn't silently numify the PV if it looks_like_number.

        Lots of operations match the first requirement (arithmetic and bitwise ops) but I can't think of anything that matches both.

        To be fair, I would have mentioned something about the rules not being practical if it hadn't already been said. In case you were actually planning on using this and didn't realize the consequences.
        isn't dualvar's made by peeking at the internals ? I think it's unfair to try to detect something without the same techniques used to create that something, but hey it's your challenge.

        On a unrelated note, is dualvar(undef,"string") zero ?
      It works only if I do not touch (i.e. expose it to various contexts) the variable before running the test:
      for my $x (0, "0", 0.0, dualvar(0,1), dualvar(0,"0 "), '----------------', 1, "foo", "00", "0 ", undef, "", dualvar(1,0), "0.0", ) { print "$x before: ",is_zero($x),"\n"; my $y = ($x+1.1).$x; print "$x after: ",is_zero($x),"\n"; }

        It works as per the OP's spec. Don't blame me for his spec being awful!

        For strings,

        0+$x; #Upd: Or 1.1 or whatever

        is effectively

        $x = dualvar(0+$x, $x) if looks_like_number($x);

        The OP was clear that dualvar(0, $anything) should be considered zero.

        It works only if I do not touch (i.e. expose it to various contexts) the variable before running the test:
        Well, yes. That's because looking at variables in Perl can actually modify them.

      Some notes:

      It could be considered to break the pure Perl rule. B is written in XS. But hey, so are operators and both come with Perl.

      It doesn't call get magic or handle overloading.

Re: Determining whether a value is zero.
by raybies (Chaplain) on Mar 10, 2011 at 13:43 UTC
    And what about -0.0 ;which, at least on my linux box, is a valid value in Perl? --Ray
      FYI, the IEEE floating point standard requires support for positive and negative zero. See Signed_Zero and IEEE_754 for more. So more like a "most computers and programming languages" thing than a Perl thing.

      Elda Taluta; Sarks Sark; Ark Arks

      I'll accept either way, under the condition it's consistent with what you'd return on dualvar(-0.0, ...)

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlmeditation [id://892390]
Approved by Corion
Front-paged by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others sharing their wisdom with the Monastery: (6)
As of 2024-04-26 09:38 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found