http://qs321.pair.com?node_id=227394

Juerd has asked for the wisdom of the Perl Monks concerning the following question:

0**0 evaluates to 1. Is this defined somewhere, or are there cases (machines, platforms, compilers, versions?) where it is undef, or maybe even NaN or an error?

perlop says it's C pow(), but my exp(3) manpage doesn't define pow(0, 0).

Juerd
- http://juerd.nl/
- spamcollector_perlmonks@juerd.nl (do not use).

Replies are listed 'Best First'.
Re: 0**0
by rob_au (Abbot) on Jan 16, 2003 at 15:57 UTC
    There has been a long discussion on this indeterminate form of exponentials previously - See More Fun with Zero!, in particular the replies from ariels and tilly.

     

    perl -le 'print+unpack("N",pack("B32","00000000000000000000001000011000"))'

      There has been a long discussion on this indeterminate form of exponentials previously - See More Fun with Zero!, in particular the replies from ariels and tilly.

      Thanks, that's quite interesting! Unfortunately, I don't understand most of the mathematical explanations (tilly++ for explaining the thing in English) and I can't find if 0**0 == 1 in Perl is coincidental or defined behaviour (ie. can I depend on 0**0 to be 1?).

      Juerd
      - http://juerd.nl/
      - spamcollector_perlmonks@juerd.nl (do not use).
      

Re: 0**0
by scain (Curate) on Jan 16, 2003 at 15:49 UTC
Re: 0**0
by belg4mit (Prior) on Jan 16, 2003 at 15:50 UTC
    It is 1 on SunOS 5.8 as well. It's probably a POSIX standard (not that I can easily tell since search engines are still stuck in the alphanumeric stone age ;-), since it is both "right" and "wrong". Anything raised to the zeroth power is defined as 1. Yet anything mulitplied by zero is 0. So they picked something and ran with it?

    Question #3
    "zero to the zeroth power"

    --
    I'm not belgian but I play one on TV.

      But in this case, nothing is getting multiplied by zero. So the rule about things being multiplied by zero would not seem to apply here.
      Another way of putting it is that the set of factors is empty. So in this, as in all cases where the set of factors is empty, the answer is 1.

      jdporter
      The 6th Rule of Perl Club is -- There is no Rule #6.

Re: 0**0
by Abigail-II (Bishop) on Jan 16, 2003 at 16:40 UTC
    # uname -srvm HP-UX B.11.00 C 9000/712 # perl -v This is perl, version 4.0 $RCSfile: perl.c,v $$Revision: 4.0.1.8 $$Date: 1993/02/05 19:39:30 $ Patch level: 36 Copyright (c) 1989, 1990, 1991, Larry Wall Perl may be copied only under the terms of either the Artistic License + or the GNU General Public License, which may be found in the Perl 4.0 source +kit. # perl -wle 'print 0**0' pow: DOMAIN error 0 #

      This is perl, version 4.0

      Thanks, but my code won't run with Perl 4 anyway. Have you got Perl 5 installed on that box? If it doesn't work, I'll have to avoid using 0**0 in my code.

      Juerd
      - http://juerd.nl/
      - spamcollector_perlmonks@juerd.nl (do not use).
      

        jkruck:<rue> % uname -srvm HP-UX B.11.00 U 9000/800 jkruck:<rue> % perl -v This is perl, version 5.005_03 built for PA-RISC1.1 Copyright 1987-1999, Larry Wall Perl may be copied only under the terms of either the Artistic License + or the GNU General Public License, which may be found in the Perl 5.0 source +kit. Complete documentation for Perl, including FAQ lists, should be found +on this system using `man perl' or `perldoc perl'. If you have access to + the Internet, point your browser at http://www.perl.com/, the Perl Home Pa +ge. jkruck:<rue> % perl -wle 'print 0**0' 1
        Clearly, if you are doing some numerical analysis, and you know in your case that 0**0 = 1 is not the right way to go, you absolutely should be checking for zeroes and handling them appropriately.

        Scott
        Project coordinator of the Generic Model Organism Database Project

Re: 0**0
by antirice (Priest) on Jan 16, 2003 at 21:32 UTC
    Well, the logarithm seems to agree.

    0**0 = 1
    log(1) / log(0) = 0

    For those of you who don't remember logs, they allow you to figure out the exponent needed to get y from x. i.e.

    log(y) / log(x) = z for x != 1 (since log(1) = 0, avoid div by zero)
    x**z = y

    Yeah, my point doesn't seem very valuable, but that's how I cope with 0**0 = 1.

    Update: I know that log(0) = -infinity. I understand that I used the limit of log(1) / log(0) as log(0) approaches -infinity (travelling from right) to get my answer that 0**0 = 1. Approaching from the left results in undef since log(-x) does not exist (this is because en = -x means that i is a factor of e, in which case n is even...in the integer sense, let's not cloud the issue with reals) and anything divided by nothing (not nothing in the zero sense but nothing in the undefined sense) doesn't exist.

    In short, depends upon which side you're coming from. I like both answers, but you 0**0 = undef guys were giving the 0**0 = 1 people a hard time.

    Another interesting note:
    0**x = ? as x approaches 0 from the right would result in ? being 0. From the left again is undefined since 0**-x = 1 / 0**x. Since 0**x = 0 for x > 0, you'd be dividing by 0 to give you the undefined value.

    So let's see, the score stands:
    0**0 = 1 => 1 point
    0**0 = 0 => 1 point
    0**0 = undef => 2 points

    Hmmm...maybe somebody from my 0**0 = 1 team can boost our score again.

    wait...

    % perl -le 'print 0**0' 1
    Let's see the scores now:
    0**0 = 0 => 1 point
    0**0 = undef => 2 points
    0**0 = 1 => since perl says so, infinite points

    ;-) Sorry this is so long.
      Except log(0) = -infinity; hence log(1)/log(0) = 0/-infinity, which is just another indeterminate.
        0/-infinity, which is just another indeterminate.

        Actually, 0/-infinity equals 0. It's not indeterminate. An indeterminate division would be something like infinity/infinity.

        buckaduck

Re: 0**0
by Courage (Parson) on Jan 17, 2003 at 07:33 UTC
    0**0 relied on underlying C library for elder perls, which is mostly 0 but could be domain error.

    Currently, as I see in source code, file "pp.c", integer power is implemented in C, and it happen to result in "1", either by accident or intentionally.

    Here is code excerpt from perl-5.8.0 to demonstrate my point:

    /* now we have integer ** positive integer. foo & (foo - 1) is zero only for a power of 2. */ if (!(baseuv & (baseuv - 1))) { /* We are raising power-of-2 to postive integer. The logic here will work for any base (even non +-integer bases) but it can be less accurate than pow (base,power) or exp (power * log (base)) wh +en the intermediate values start to spill out of the m +antissa. With powers of 2 we know this can't happen. And powers of 2 are the favourite thing for per +l programmers to notice ** not doing what they me +an. */ NV result = 1.0; NV base = baseuok ? baseuv : -(NV)baseuv; int n = 0; /* The logic is this. x ** n === x ** m1 * x ** m2 where n = m1 + m2 so as 42 is 32 + 8 + 2 x ** 42 can be written as x ** 32 * x ** 8 * x ** 2 I can calculate x ** 2, x ** 4, x ** 8 etc triv +ially: x ** 2n is x ** n * x ** n So I loop round, squaring x each time (x, x ** 2, x ** 4, x ** 8) and multiply the re +sult by the x-value whenever that bit is set in the +power. To finish as soon as possible I zero bits in th +e power when I've done them, so that power becomes zero + when I clear the last bit (no more to do), and the l +oop terminates. */

    Courage, the Cowardly Dog

Re: 0**0
by busunsl (Vicar) on Jan 17, 2003 at 07:20 UTC
      Every math teacher and such I've run across in the past 7 or 8 years at least has told me that 0^0 was eventually defined as equal to 1.

      Makeshifts last the longest.

Re: 0**0
by JaWi (Hermit) on Jan 16, 2003 at 16:03 UTC
    Hi Juerd,

    0**0 should be somewhere between 0 and undefined (source: here). So, actually, it should return undef, since that's what most (if not all) math-books say.

    Hope it helps,

    Greets,

    -- JaWi

    "A chicken is an egg's way of producing more eggs."

      I disagree. Yes, there are situations where 0^0 should be undefined, but there are also several cases where it should be 1. Given that, I don't want my numerical methods package to be crashing all the time because Perl thinks it should be undef.

      The fact is, the coder should know which case he is interested in (1 or undef as the answer); I think it is better from a coding perspective to check for the undef case, and just allow the 0^0 == 1 case without special checking.

      Now, who the heck is writing numerical methods packages in Perl--FORTRAN is the way to go :-)

      Scott
      Project coordinator of the Generic Model Organism Database Project

        Ok, I see your point. However, if you would define 0**0 as being 1, you're making an exception "just because it is so darn handy while programming". In that case, you would need to handle other exceptions like, for example, sqrt(-1) as well, since this would be handy as well...

        -- JaWi

        "A chicken is an egg's way of producing more eggs."

Re: 0**0
by toma (Vicar) on Jan 18, 2003 at 05:25 UTC
    Perhaps this is why engineers want 0**0 = 1
    foreach my $close_to_zero (1e-3, 1e-4, 1e-5, 1e-6, 1e-7, 1e-8, 1e-9, 1e-10, 1e-11, 1e-12, 1e-13, ){ print $close_to_zero**$close_to_zero,"\n"; }
    produces
    0.993116048420934 0.999079389984462 0.999884877372469 0.999986184584876 0.999998388191734 0.99999981579321 0.999999979276734 0.999999997697415 0.999999999746716 0.999999999972369 0.999999999997007

    If you approach zero from the negative side, it doesn't work. There are many other directions you can approach from, using complex numbers. From these directions the answer also seems to head toward a limit of 1.

    use Math::Complex; my $j=sqrt(-1)/100; foreach my $close_to_zero (-1e-3-$j*1e-3, -1e-4-$j*1e-4, -1e-5-$j*1e-5, -1e-6-$j*1e-6, -1e-7-$j*1e-7, -1e-8-$j*1e-8, -1e-9-$j*1e-9, -1e-10-$j*1e-10, -1e-11-$j*1e-11, -1e-12-$j*1e-12, -1e-13-$j*1e-13, ){ print $close_to_zero**$close_to_zero,"\n"; }
    prints
    1.00689492851834+0.00322274943578533i 1.00091826683245+0.000322665621543586i 1.00011482165982+3.24709453669811e-05i 1.00001378423429+3.2697926634863e-06i 1.00000160867421+3.29277874043755e-07i 1.00000018389316+3.31579990412048e-08i 1.0000000206919+3.33882521438423e-09i 1.00000000229945+3.36185100395793e-10i 1.00000000025297+3.38487684801375e-11i 1.0000000000276+3.40790269818147e-12i 1.00000000000299+3.43092854902761e-13i

    So my engineering view is that 0**0==1 most of the time, for large values of zero.

    It should work perfectly the first time! - toma

Re: 0**0
by osama (Scribe) on Jan 17, 2003 at 10:35 UTC

    I thought that anything**0=1, even if it's 0**0, it's actually very logical.

    Maybe engineers prefer 0**0=1, mathematicians prefer undef!

      It depends on where you're coming from. You're taking the limit of x**0 with x -> 0. But, take 0**x, which is zero for any value x > 0, thus when x -> 0... you end up with a different value for 0**0.

      That's why 0**0 is undefined. You can get different values for it, which are all valid in some way.