After finding blazar's bug in bigint? posting, I decided to beat on bignum to see how it handled logs (generally, as far as I could tell, perfectly well). However, this gave me a surprise:

#!perl use warnings; use strict; use bignum; my $n = -1; print "10 ** $n = " . 10 ** $n . "\n";
returns this:
10 ** -1 = NaN

which is, obviously, wrong. I'm using ActiveState Perl, (Binary build 819 [267479]). Has anybody seen this with other Perls? (Please don't tell me it should be undefined; the answer should be 0.1, which it is if the use bignum; line is commented out). I've submitted a bug to ActiveState, but I'm curious as to whether it's more basic than that.


I've filed a bug report (http://rt.perl.org/rt3/Ticket/Display.html?id=41050.). Now, to try to come up with a patch...

emc

At that time [1909] the chief engineer was almost always the chief test pilot as well. That had the fortunate result of eliminating poor engineering early in aviation.

—Igor Sikorsky, reported in AOPA Pilot magazine February 2003.

Replies are listed 'Best First'.
Re: use bignum and exponentiation
by syphilis (Archbishop) on Dec 02, 2006 at 00:28 UTC
    If you 'use bignum;' then both "10" and "$n" are Math::BigInt objects. I haven't checked it out, but I suspect that when you raise one Math::BigInt object to the power of another Math::BigInt object, the result is also a Math::BigInt object - which, in your case, needs to contain the value '0.1' .... but you can't expect a Math::BigInt object to hold such a value.

    The following should produce the correct answer but doesn't:
    D:\>perl -Mbignum -e "print 10.0 ** -1.0" NaN
    Unfortunately, the "10.0" and "-1.0" are simply being made into Math::BigInt objects with values of 10 and -1, respectively. If they were created as Math::BigFloat objects (as in my next one liner) everything would work fine:
    D:\>perl -Mbignum -e "print 10.1 ** -1.1" 0.07856814306418730376003456559872468142155

    Cheers,
    Rob

      However, one of the bignum samples:

      perl -Mbignum -le 'print sqrt(33)'

      behaves in one of the ways I would expect, in that it returns:

      5.74456264653802865985061146821892931822

      The other way I would expect would be for it to return 5, which would be cosnistent with 33 being treated as an integer.

      Also, another sample:

      perl -Mbignum -le 'print 2 ** 0.5' returns: 1.41421356237309504880168872420969807857

      This is also inconsistent with 2**0.5 being treated as an integer.

      Returning NaN for raising an integer to a negative power is not consistent with the documentation (nowhere is it said that "raising an integer to a negative power results in NaN) and it is also inconsistent with other Perl behavior (1/10 doesn't return NaN)

      Also, I just tried (on my FreeBSD box, at home) this:

      perl -Mbignum -le 'print 10.01 ** -1'

      and had it returned

      0.0999000999000999000999000999000999000999

      This is consistent with syphilis' conmments.

      emc

      At that time [1909] the chief engineer was almost always the chief test pilot as well. That had the fortunate result of eliminating poor engineering early in aviation.

      —Igor Sikorsky, reported in AOPA Pilot magazine February 2003.
        The other way I would expect would be for it to return 5, which would be cosnistent with 33 being treated as an integer.

        A return of "5" is what I would have expected. Afaict, the "33" is a Math::BigInt object, yet for some reason the module's author has apparently decided to implement some cross-class overloading and have a Math::BigFloat object returned when sqrt() is called with 'use bignum'. I guess, therefore, it might be possible (via some recoding of the bignum module) to have the overloaded ** operator return a Math::BigFloat object when the exponent is a negative integer.

        I don't particularly like cross-class overloading ... it's a cute and clever thing to do, but one just doesn't know in advance what one is going to get in return. And there's no guarantee that DWIMness is being met, anyway. I would recommend that one uses Math::BigInt/Math::BigFloat instead of bignum.

        (I could be way off with my diagnosis ... I haven't delved into the source to verify that I've got it right. I have made my assessments based on a few test programs that Devel::Peek::Dump()ed the various arguments and returns.)

        Cheers,
        Rob
Re: use bignum and exponentiation
by rhesa (Vicar) on Dec 01, 2006 at 23:32 UTC
    10 ** -1 = NaN This is perl, v5.8.4 built for x86_64-linux-thread-multi This is perl, v5.8.5 built for i386-linux-thread-multi This is perl, v5.8.8 built for i686-linux
    weird!
      This is perl, v5.8.8 built for i486-linux-gnu-thread-multi

      Fails for me as well.
Re: use bignum and exponentiation
by sgt (Deacon) on Dec 04, 2006 at 23:56 UTC

    I get the same failures on cygwin :( this should be filed as a serious bug. Too bad really, usually I use Math::Pari so I don't test bignum often, o just to test a new version of M::p

    This is perl, v5.8.7 built for cygwin-thread-multi-64int (with 1 registered patch, see perl -V for more detail)

    % stephan@labaule (/home/stephan) % % perl -Mbignum -e 'print 10**-1.0' NaN % stephan@labaule (/home/stephan) % % perl -Mbignum -e 'print 10.0**-1.0' NaN % stephan@labaule (/home/stephan) % % perl -Mbignum -e 'print 10**-1' NaN
    hth --stephan