Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   Perl Misc (http://www.velocityreviews.com/forums/f67-perl-misc.html)
-   -   bignum::bdiv() not working correctly on integers (http://www.velocityreviews.com/forums/t911673-bignum-bdiv-not-working-correctly-on-integers.html)

jl_post@hotmail.com 10-28-2009 04:57 PM

bignum::bdiv() not working correctly on integers
 

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

Steve C 10-28-2009 06:19 PM

Re: bignum::bdiv() not working correctly on integers
 
jl_post@hotmail.com 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)


jl_post@hotmail.com 10-28-2009 06:36 PM

Re: bignum::bdiv() not working correctly on integers
 
On Oct 28, 12:19 pm, Steve C <smallp...@juno.com> 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

Steve C 10-28-2009 06:49 PM

Re: bignum::bdiv() not working correctly on integers
 
jl_post@hotmail.com wrote:
> On Oct 28, 12:19 pm, Steve C <smallp...@juno.com> 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.


jl_post@hotmail.com 10-28-2009 07:21 PM

Re: bignum::bdiv() not working correctly on integers
 
On Oct 28, 12:49*pm, Steve C <smallp...@juno.com> 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

Steve C 10-28-2009 08:05 PM

Re: bignum::bdiv() not working correctly on integers
 
jl_post@hotmail.com wrote:
> On Oct 28, 12:49 pm, Steve C <smallp...@juno.com> 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


jl_post@hotmail.com 10-28-2009 08:08 PM

Re: bignum::bdiv() not working correctly on integers
 
On Oct 28, 12:19 pm, Steve C <smallp...@juno.com> 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


All times are GMT. The time now is 02:51 AM.

Powered by vBulletin®. Copyright ©2000 - 2014, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.