Skip Menu |

This queue is for tickets about the bignum CPAN distribution.

Report information
The Basics
Id: 18025
Status: resolved
Worked: 1.7 hours (100 min)
Priority: 0/
Queue: bignum

People
Owner: TELS [...] cpan.org
Requestors: martin [...] snowplow.org
Cc:
AdminCc:

Bug Information
Severity: Normal
Broken in: 0.17
Fixed in: (no value)



Subject: bignum/bigrat can lead to a number that is both 1 and 0
The following test code, when run on the stock cygwin build of perl 5.8.7, fails. Specifically, the value $ev prints as "1", but so does the value 1-$ev. #!perl use strict; use warnings; use Test::More tests => 4; use bignum; my $lnev = -7 / (10**17); my $ev=exp($lnev); is( sprintf('%0.5f',$ev) , '1.00000', '($ev) is approx. 1' ); is( sprintf('%0.5f',1-$ev) , '0.00000', '(1-$ev) is approx. 0' ); is( sprintf('%0.5f',1-"$ev") , '0.00000', '(1-"$ev") is approx. 0' ); cmp_ok( $ev, '!=', 0, '$ev should not equal 0'); __END__ Note that on my copy of 5.8.7, tests 2 and 4 fail. I have it on good authority that on perl 5.8.6, test 4 succeeds, though test 2 still fails. I _think_ it has something to do with the magic bignum applies to the exp function, rather than any magic being applied to constants since the following code properly prints 0: #!perl use Math::BigFloat; print ((new Math::BigFloat("1")) - exp(new Math::BigFloat("-7")/ (new Math::BigFloat("10")**(new Math::BigFloat("17"))))); __END__ But this code prints "1"; the only difference is "use bignum": #!perl use bignum; use Math::BigFloat; print ((new Math::BigFloat("1")) - exp(new Math::BigFloat("-7")/ (new Math::BigFloat("10")**(new Math::BigFloat("17"))))); __END__
From: nospam-abuse [...] bloodgate.com
On Mon Mar 06 21:05:32 2006, guest wrote: Show quoted text
> The following test code, when run on the stock cygwin build of perl > 5.8.7, fails. Specifically, the value $ev prints as "1", but so does > the value 1-$ev. > > #!perl > use strict; > use warnings; > use Test::More tests => 4; > use bignum; > > my $lnev = -7 / (10**17); > my $ev=exp($lnev); > > is( sprintf('%0.5f',$ev) , '1.00000', '($ev) is approx. 1' ); > is( sprintf('%0.5f',1-$ev) , '0.00000', '(1-$ev) is approx. 0' ); > is( sprintf('%0.5f',1-"$ev") , '0.00000', '(1-"$ev") is approx. 0' ); > > cmp_ok( $ev, '!=', 0, '$ev should not equal 0'); > __END__ > > Note that on my copy of 5.8.7, tests 2 and 4 fail. I have it on good > authority that on perl 5.8.6, test 4 succeeds, though test 2 still fails.
This is very wierd, I have now spent some time trying to figure out why $ev can be both 0 and 1 at the same time, but have no clue yet. On Perl 5.8.8, test 2 fails and test 4 passes, btw. Show quoted text
> I _think_ it has something to do with the magic bignum applies to the > exp function, rather than any magic being applied to constants since the > following code properly prints 0: > > #!perl > use Math::BigFloat; > print ((new Math::BigFloat("1")) - > exp(new Math::BigFloat("-7")/ > (new Math::BigFloat("10")**(new Math::BigFloat("17"))))); > __END__ > > But this code prints "1"; the only difference is "use bignum": > > #!perl > use bignum; > use Math::BigFloat; > print ((new Math::BigFloat("1")) - > exp(new Math::BigFloat("-7")/ > (new Math::BigFloat("10")**(new Math::BigFloat("17"))))); > __END__
I have no idea. Best wishes, Tels
On Sat Jan 27 06:59:44 2007, TELS wrote: Show quoted text
> On Mon Mar 06 21:05:32 2006, guest wrote:
> > The following test code, when run on the stock cygwin build of perl > > 5.8.7, fails. Specifically, the value $ev prints as "1", but so does
Okay, the issue boils down to sometimes int(1.0) == 0 :( Since the value exp() returns results in int($ev) == 0, the constructed bigint number is wrong. This looks like a perl bug to me, so I posted a question to p5p about this. Here is a testscript showing it doesn't have to do anything with BigInt: #!perl use strict; use warnings; use Test::More tests => 6; my $lnev = -7 / (10**17); my $ev=exp($lnev); my $nv = 1.0; use Devel::Peek; print Dump($ev); print Dump($nv); is( $ev, '1', '$ev == 1'); is( sprintf('%0.15f',$ev) , '1.000000000000000', '($ev) is approx. 1' ); is( int($ev), '1', 'int($ev) == 1'); is( $nv, '1', '$nv == 1'); is( sprintf('%0.15f',$nv) , '1.000000000000000', '($nv) is approx. 1' ); is( int($nv), '1', 'int($nv) == 1'); exit; Output: 1..6 SV = NV(0x682f70) at 0x76eaa0 REFCNT = 1 FLAGS = (PADBUSY,PADMY,NOK,pNOK) NV = 1 SV = NV(0x682f78) at 0x76ea90 REFCNT = 1 FLAGS = (PADBUSY,PADMY,NOK,pNOK) NV = 1 ok 1 - $ev == 1 ok 2 - ($ev) is approx. 1 not ok 3 - int($ev) == 1 # Failed test 'int($ev) == 1' # in fail.pl at line 16. # got: '0' # expected: '1' ok 4 - $nv == 1 ok 5 - ($nv) is approx. 1 ok 6 - int($nv) == 1 # Looks like you failed 1 test of 6 I am cnsidering closing this bug as there is nothing I can do inside bignum/bigrat to detect this sort of problem (if int() doesn't work correctly, well, then my code can't work correcty). Sorry! Thanx a lot for your bug report!
CC: bug-bignum [...] rt.cpan.org
Subject: Re: [rt.cpan.org #18025] bignum/bigrat can lead to a number that is both 1 and 0
Date: Fri, 30 Mar 2007 23:27:58 +0000
To: martin [...] snowplow.org
From: Tels <nospam-abuse [...] bloodgate.com>
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Moin,. On Friday 30 March 2007 21:08:23 martin@snowplow.org wrote: Show quoted text
> " via RT" <bug-bignum@rt.cpan.org> writes:
> > <URL: http://rt.cpan.org/Ticket/Display.html?id=18025 > > > > > On Sat Jan 27 06:59:44 2007, TELS wrote:
> >> On Mon Mar 06 21:05:32 2006, guest wrote:
> >> > The following test code, when run on the stock cygwin build of perl > >> > 5.8.7, fails. Specifically, the value $ev prints as "1", but so > >> > does
> > > > Okay, the issue boils down to sometimes int(1.0) == 0 :( > > > > Since the value exp() returns results in int($ev) == 0, the constructed > > bigint number is wrong. This looks like a perl bug to me, so I posted a > > question to p5p about this. Here is a testscript showing it doesn't > > have to do anything with BigInt:
Oh, btw, you just discovered another bug: perl -Mbignum -le 'print exp(8)' 2980.95798704173 exp() should be overloaded but it isn't! Wow thank you :) All the best, Tels - -- Signed on Fri Mar 30 23:27:57 2007 with key 0x93B84C15. View my photo gallery: http://bloodgate.com/photos PGP key on http://bloodgate.com/tels.asc or per email. /* Too drunk - debug later */ -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.2 (GNU/Linux) iQEVAwUBRg2c/ncLPEOTuEwVAQIz/Qf+Kz8HRre9B7RTOlnack8fpnDi9KpiMgAu veHoE2FLp5NnT/jrnN+oukWqlpWjpoinnyvyauchnetdKaZMcW2IQTQ0pcqHmguD XOFfDv3PWy872M+EavFS7S4QsfwkSfqoss80zrxxP4g38jLp8DWI2f7Eqj/hnQh4 fr3apF9Wp2MfHDdCulZ3bXMBaPqvZ2kSWBr5wL7RF5nGzYhSseTat2ioiUIfnpls Up0wbOSKnXYoOas0tccG2RRzACZZbudN0XQdL4m55jlsARGuOFzQfEa/TsTb7Bia JekSpE3YD8Gv07pIWrzMMpn/euu7kK29QoCdT7EtWqUV8w+71q8GiQ== =/0jQ -----END PGP SIGNATURE-----
This issue has been fixed with the release of Math::BigInt 1.82. However, I am leaving this bug open because there are still 3 "holes" in the overloading, making it possible to recreate the situation: * cos(), sin() and atan2() are not "properly" overloaded: perl -MTest::More -wle 'plan tests=>2;my $e = cos(0.00000002); is ($e,"1","e == 1"); is(int($e),"1","int(e) == 1")' 1..2 ok 1 - e == 1 not ok 2 - int(e) == 1 # Failed test 'int(e) == 1' # in -e at line 1. # got: '0' # expected: '1' # Looks like you failed 1 test of 2. All the best, Tels
Marking this as resolved now: # perl -Mbignum -MTest::More -wle 'plan tests=>2;my $e = cos(0.000000000000000000001); is ($e,"1","e == 1"); is(int($e),"1","int(e) == 1")' 1..2 ok 1 - e == 1 ok 2 - int(e) == 1 e.g. cos(), sin() and atan2() are now properly overloaded. In addition, hex() and oct() are overloaded, too, so all the holes should be plugged now. All the best, Tels