bignum::bdiv() not working correctly on integers

Discussion in 'Perl Misc' started by jl_post@hotmail.com, Oct 28, 2009.

  1. Guest

    Hi,

    I've recently discovered that if I create a "bignum" object in Perl
    and call the ->bdiv() method, sometimes the object will get modified
    and sometimes it won't. Here's a sample program that illustrates what
    I'm talking about:

    #!/usr/bin/perl

    use strict;
    use warnings;

    use bignum;

    my $n1 = 6.6;
    print "\$n1 before \$n1->bdiv(2): $n1\n"; # prints 6.6
    $n1->bdiv(2);
    print "\$n1 after \$n1->bdiv(2): $n1\n"; # prints 3.3

    print "\n";

    my $n2 = 6;
    print "\$n2 before \$n2->bdiv(2): $n2\n"; # prints 6
    $n2->bdiv(2);
    print "\$n2 after \$n2->bdiv(2): $n2\n"; # prints 6 (error?)

    __END__


    I've tested this script on both Windows and Unix, and the output is
    the same. I changed "use bignum" to "use bigint" and I saw the
    expected 6, 3, and 6, 3 as output. (The floating-point numbers were
    truncated, but that's no surprise since we're working with integers.)

    I also changed "bdiv" to "bmul" (using the "bignum" module) and I
    saw the expected 6.6, 13.2, and 6, 12 as output, so apparently
    bignum::dmul() works consistently.

    I've noticed that bignum::bdiv() seems to modify the calling object
    if the value is a floating-point number (that is, cannot be
    represented as an integer). But if the calling object is an integer
    (even one with a decimal point like 6.0), then bignum::bdiv() does not
    modify it.

    I noticed that if I print out ref($n1) and ref($n2), I see that $n1
    is a Math::BigFloat and that $n2 is a Math::BigInt. So I might think
    that the problem lies in the Math::BigInt module. However, when I
    change "use bignum" to "use bigint", they both become Math::BigInt
    objects, but now the bdiv() method is modifying the calling object (as
    I think it should).

    So it doesn't look like the problem is with Math::BigInt, but
    rather with the "bignum" module.

    Is this incosistent behavior of the "bignum" module a bug, or am I
    missing something? I haven't seen much code that uses the "bigint"
    and "bignum" modules, so as far as I know they're deprecated, but I
    haven't read anything to that effect.

    -- Jean-Luc
     
    , Oct 28, 2009
    #1
    1. Advertising

  2. Steve C Guest

    wrote:
    > Hi,
    >
    > I've recently discovered that if I create a "bignum" object in Perl
    > and call the ->bdiv() method, sometimes the object will get modified
    > and sometimes it won't. Here's a sample program that illustrates what
    > I'm talking about:
    >
    > #!/usr/bin/perl
    >
    > use strict;
    > use warnings;
    >
    > use bignum;
    >
    > my $n1 = 6.6;
    > print "\$n1 before \$n1->bdiv(2): $n1\n"; # prints 6.6
    > $n1->bdiv(2);
    > print "\$n1 after \$n1->bdiv(2): $n1\n"; # prints 3.3
    >
    > print "\n";
    >
    > my $n2 = 6;
    > print "\$n2 before \$n2->bdiv(2): $n2\n"; # prints 6
    > $n2->bdiv(2);
    > print "\$n2 after \$n2->bdiv(2): $n2\n"; # prints 6 (error?)
    >
    > __END__
    >
    >
    > I've tested this script on both Windows and Unix, and the output is
    > the same. I changed "use bignum" to "use bigint" and I saw the
    > expected 6, 3, and 6, 3 as output. (The floating-point numbers were
    > truncated, but that's no surprise since we're working with integers.)
    >
    > I also changed "bdiv" to "bmul" (using the "bignum" module) and I
    > saw the expected 6.6, 13.2, and 6, 12 as output, so apparently
    > bignum::dmul() works consistently.
    >
    > I've noticed that bignum::bdiv() seems to modify the calling object
    > if the value is a floating-point number (that is, cannot be
    > represented as an integer). But if the calling object is an integer
    > (even one with a decimal point like 6.0), then bignum::bdiv() does not
    > modify it.
    >
    > I noticed that if I print out ref($n1) and ref($n2), I see that $n1
    > is a Math::BigFloat and that $n2 is a Math::BigInt. So I might think
    > that the problem lies in the Math::BigInt module. However, when I
    > change "use bignum" to "use bigint", they both become Math::BigInt
    > objects, but now the bdiv() method is modifying the calling object (as
    > I think it should).
    >
    > So it doesn't look like the problem is with Math::BigInt, but
    > rather with the "bignum" module.
    >
    > Is this incosistent behavior of the "bignum" module a bug, or am I
    > missing something? I haven't seen much code that uses the "bigint"
    > and "bignum" modules, so as far as I know they're deprecated, but I
    > haven't read anything to that effect.
    >
    > -- Jean-Luc


    bigint promotes the type to BigInt or BigFloat as required.
    When you start with a BigInt and divide by a float it must make
    a new bignum. You can see it explicitly by doing this:

    my $n1 = new Math::BigFloat 6;
    print "\$n1 before \$n1->bdiv(2): $n1\n"; # prints 6
    $n1->bdiv(2);
    print "\$n1 after \$n1->bdiv(2): $n1\n"; # prints 3

    print "\n";

    my $n2 = new Math::BigInt 6;
    print "\$n2 before \$n2->bdiv(2): $n2\n"; # prints 6
    $n2->bdiv(2);
    print "\$n2 after \$n2->bdiv(2): $n2\n"; # prints 6 (unexpected)
     
    Steve C, Oct 28, 2009
    #2
    1. Advertising

  3. Guest

    On Oct 28, 12:19 pm, Steve C <> wrote:
    >
    > bigint promotes the type to BigInt or BigFloat as required.
    > When you start with a BigInt and divide by a float it must make
    > a new bignum. You can see it explicitly by doing this:
    >
    > my $n1 = new Math::BigFloat 6;
    > print "\$n1 before \$n1->bdiv(2): $n1\n"; # prints 6
    > $n1->bdiv(2);
    > print "\$n1 after \$n1->bdiv(2): $n1\n"; # prints 3
    >
    > print "\n";
    >
    > my $n2 = new Math::BigInt 6;
    > print "\$n2 before \$n2->bdiv(2): $n2\n"; # prints 6
    > $n2->bdiv(2);
    > print "\$n2 after \$n2->bdiv(2): $n2\n"; # prints 6 (unexpected)



    That's not the behavior I'm getting. When I run your code in the
    following script:


    #!/usr/bin/perl

    use strict;
    use warnings;

    use Math::BigFloat;
    my $n1 = new Math::BigFloat 6;
    print "\$n1 before \$n1->bdiv(2): $n1\n"; # prints 6
    $n1->bdiv(2);
    print "\$n1 after \$n1->bdiv(2): $n1\n"; # prints 3

    print "\n";

    use Math::BigInt;
    my $n2 = new Math::BigInt 6;
    print "\$n2 before \$n2->bdiv(2): $n2\n"; # prints 6
    $n2->bdiv(2);
    print "\$n2 after \$n2->bdiv(2): $n2\n"; # prints 3

    __END__


    I see as output 6, 3 and 6, 3 (and not 6, 3, and 6, 6 like you saw).

    But even if Math::BigInt::bdiv() did make a new bignum, I'd still
    expect the bdiv() method to behave as documented in the "perldoc
    Math::BigInt" documentation, which is to change the value of the
    calling object.

    I noticed that just placing the "use bignum;" like anywhere in the
    script causes weird things to happen. Even if I put it in as the last
    line of my above script (but before the __END__ tag, of course) the
    output I see changes to 6, 6 and 6, 6.

    Did you have "use bignum;" (or "use bigint;") anywhere in your
    script? If you do, try removing it and running the script again. You
    might get different output.

    And in case anyone wants to know, "perl -v" gives me this output:

    On Windows: This is perl, v5.10.0 built for MSWin32-x86-multi-thread

    On Linux: This is perl, v5.8.4 built for i386-linux-thread-multi

    -- Jean-Luc
     
    , Oct 28, 2009
    #3
  4. Steve C Guest

    wrote:
    > On Oct 28, 12:19 pm, Steve C <> wrote:
    >> bigint promotes the type to BigInt or BigFloat as required.
    >> When you start with a BigInt and divide by a float it must make
    >> a new bignum. You can see it explicitly by doing this:
    >>
    >> my $n1 = new Math::BigFloat 6;
    >> print "\$n1 before \$n1->bdiv(2): $n1\n"; # prints 6
    >> $n1->bdiv(2);
    >> print "\$n1 after \$n1->bdiv(2): $n1\n"; # prints 3
    >>
    >> print "\n";
    >>
    >> my $n2 = new Math::BigInt 6;
    >> print "\$n2 before \$n2->bdiv(2): $n2\n"; # prints 6
    >> $n2->bdiv(2);
    >> print "\$n2 after \$n2->bdiv(2): $n2\n"; # prints 6 (unexpected)

    >
    >
    > That's not the behavior I'm getting. When I run your code in the
    > following script:
    >
    >
    > #!/usr/bin/perl
    >
    > use strict;
    > use warnings;
    >
    > use Math::BigFloat;
    > my $n1 = new Math::BigFloat 6;
    > print "\$n1 before \$n1->bdiv(2): $n1\n"; # prints 6
    > $n1->bdiv(2);
    > print "\$n1 after \$n1->bdiv(2): $n1\n"; # prints 3
    >
    > print "\n";
    >
    > use Math::BigInt;
    > my $n2 = new Math::BigInt 6;
    > print "\$n2 before \$n2->bdiv(2): $n2\n"; # prints 6
    > $n2->bdiv(2);
    > print "\$n2 after \$n2->bdiv(2): $n2\n"; # prints 3
    >
    > __END__
    >
    >
    > I see as output 6, 3 and 6, 3 (and not 6, 3, and 6, 6 like you saw).
    >
    > But even if Math::BigInt::bdiv() did make a new bignum, I'd still
    > expect the bdiv() method to behave as documented in the "perldoc
    > Math::BigInt" documentation, which is to change the value of the
    > calling object.
    >
    > I noticed that just placing the "use bignum;" like anywhere in the
    > script causes weird things to happen. Even if I put it in as the last
    > line of my above script (but before the __END__ tag, of course) the
    > output I see changes to 6, 6 and 6, 6.
    >
    > Did you have "use bignum;" (or "use bigint;") anywhere in your
    > script? If you do, try removing it and running the script again. You
    > might get different output.
    >
    > And in case anyone wants to know, "perl -v" gives me this output:
    >
    > On Windows: This is perl, v5.10.0 built for MSWin32-x86-multi-thread
    >
    > On Linux: This is perl, v5.8.4 built for i386-linux-thread-multi
    >
    > -- Jean-Luc


    I was explaining what bignum does. Math::BigInt and Math::BigFloat
    act as expected by themselves. Sorry I forgot to include the
    use bignum in my post.
     
    Steve C, Oct 28, 2009
    #4
  5. Guest

    On Oct 28, 12:49 pm, Steve C <> wrote:
    >
    > I was explaining what bignum does.  Math::BigInt and Math::BigFloat
    > act as expected by themselves.  Sorry I forgot to include the
    > use bignum in my post.



    Okay, but if I run my most-recently posted script with "use
    bignum;" I get 6, 6 and 6, 6. If I run it without that line I see 6,
    3, and 6, 3. I still don't see how you got 6, 3, and 6, 6.

    Can you post the script you used?

    -- Jean-Luc
     
    , Oct 28, 2009
    #5
  6. Steve C Guest

    wrote:
    > On Oct 28, 12:49 pm, Steve C <> wrote:
    >> I was explaining what bignum does. Math::BigInt and Math::BigFloat
    >> act as expected by themselves. Sorry I forgot to include the
    >> use bignum in my post.

    >
    >
    > Okay, but if I run my most-recently posted script with "use
    > bignum;" I get 6, 6 and 6, 6. If I run it without that line I see 6,
    > 3, and 6, 3. I still don't see how you got 6, 3, and 6, 6.
    >
    > Can you post the script you used?
    >
    > -- Jean-Luc



    use bignum;

    my $n1 = new Math::BigFloat 6;
    print "\$n1 before \$n1->bdiv(2): $n1\n"; # prints 6
    $n1->bdiv(2);
    print "\$n1 after \$n1->bdiv(2): $n1\n"; # prints 3

    print "\n";

    my $n2 = new Math::BigInt 6;
    print "\$n2 before \$n2->bdiv(2): $n2\n"; # prints 6
    $n2->bdiv(2);
    print "\$n2 after \$n2->bdiv(2): $n2\n"; # prints 6
     
    Steve C, Oct 28, 2009
    #6
  7. Guest

    On Oct 28, 12:19 pm, Steve C <> wrote:
    >
    > bigint promotes the type to BigInt or BigFloat as required.
    > When you start with a BigInt and divide by a float it must make
    > a new bignum.


    I disagree. When I run this code:


    #!/usr/bin/perl
    use strict;
    use warnings;

    use Math::BigInt;
    my $n = Math::BigInt->new(6);

    print "\$n before \$n->bdiv(2): $n\n"; # prints 6
    print "\\\$n = ", \$n, "\n";
    print "ref(\$n) = ", ref($n), "\n\n";
    $n->bdiv(2);
    print "\$n after \$n->bdiv(2): $n\n"; # prints 3
    print "\\\$n = ", \$n, "\n";
    print "ref(\$n) = ", ref($n), "\n";
    __END__


    I see this output:

    $n before $n->bdiv(2): 6
    \$n = REF(0x22c725c)
    ref($n) = Math::BigInt

    $n after $n->bdiv(2): 3
    \$n = REF(0x22c725c)
    ref($n) = Math::BigInt

    So not only do I see 6 and 3 as output, I also see that $n is still
    the same object before as after the call to ->bdiv() (in other words,
    it never made a copy).

    Now I run the following script, which is identical to the previous
    one except that it has the "use bignum;" line at the bottom:


    #!/usr/bin/perl
    use strict;
    use warnings;

    use Math::BigInt;
    my $n = Math::BigInt->new(6);

    print "\$n before \$n->bdiv(2): $n\n"; # prints 6
    print "\\\$n = ", \$n, "\n";
    print "ref(\$n) = ", ref($n), "\n\n";
    $n->bdiv(2);
    print "\$n after \$n->bdiv(2): $n\n"; # prints 6 (why?)
    print "\\\$n = ", \$n, "\n";
    print "ref(\$n) = ", ref($n), "\n";

    use bignum;
    __END__


    Now I get this output:

    $n before $n->bdiv(2): 6
    \$n = REF(0x99725c)
    ref($n) = Math::BigInt

    $n after $n->bdiv(2): 6
    \$n = REF(0x99725c)
    ref($n) = Math::BigInt

    As before, $n is still the same object (that is, it was not
    replaced with a copy) and it's still a Math::BigInt object, but now
    the output is 6 and 6.

    Why is that? Why is just the simple inclusion of the "use bignum;"
    line enough to change the behavior of Math::BigInt::bdiv() ?

    "perldoc Math::BigInt" explicitly says that $n will be modified
    when calling the bdiv() method. If that's the case, why does the
    first script do just that but the second script does not? (There's
    nothing I found in the "perldoc bignum" documentation that says
    otherwise.)

    -- Jean-Luc
     
    , Oct 28, 2009
    #7
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. =?Utf-8?B?SUdvdFlvdXJEb3ROZXQ=?=

    sort not working correctly

    =?Utf-8?B?SUdvdFlvdXJEb3ROZXQ=?=, Aug 18, 2004, in forum: ASP .Net
    Replies:
    4
    Views:
    514
    =?Utf-8?B?SUdvdFlvdXJEb3ROZXQ=?=
    Aug 18, 2004
  2. Hermit Dave

    Re: dropdownlist box not working correctly

    Hermit Dave, Sep 2, 2004, in forum: ASP .Net
    Replies:
    0
    Views:
    418
    Hermit Dave
    Sep 2, 2004
  3. Stuart Palmer

    History not working correctly

    Stuart Palmer, Jun 2, 2004, in forum: HTML
    Replies:
    0
    Views:
    384
    Stuart Palmer
    Jun 2, 2004
  4. rosemm
    Replies:
    2
    Views:
    798
    Martin Honnen
    Apr 5, 2005
  5. Mr Magpie
    Replies:
    7
    Views:
    132
    Mr Magpie
    May 1, 2007
Loading...

Share This Page