Login | Register For Free | Help
Search for: (Advanced)

Mailing List Archive: Perl: porters

[perl #28538] Math::BigInt doesn't grok "0 but true"

 

 

Perl porters RSS feed   Index | Next | Previous | View Threaded


perlbug-followup at perl

Apr 13, 2004, 5:08 PM

Post #1 of 10 (127 views)
Permalink
[perl #28538] Math::BigInt doesn't grok "0 but true"

# New Ticket Created by Zefram
# Please include the string: [perl #28538]
# in the subject line of all future correspondence about this issue.
# <URL: http://rt.perl.org:80/rt3/Ticket/Display.html?id=28538 >



This is a bug report for perl from zefram [at] fysh,
generated with the help of perlbug 1.34 running under perl v5.8.3.


-----------------------------------------------------------------
[Please enter your report here]

$ perl -MMath::BigInt -we 'print Math::BigInt->new("0"), "\n"'
0
$ perl -MMath::BigInt -we 'print Math::BigInt->new("0 but true"), "\n"'
NaN

Similar and probably related:

$ perl -MScalar::Util=dualvar -MMath::BigInt -we 'print Math::BigInt->new(dualvar(3, "foo")), "\n"'
NaN
$ perl -MScalar::Util=dualvar -MMath::BigInt -we 'print Math::BigInt->new(dualvar(3, "5")), "\n"'
3

Looks like Math::BigInt is examining the string value for validity
check, but then actually using the numeric value if it finds the string
sufficiently numeric. It really ought to be using looks_like_number.

Workaround for this problem involves avoiding implicit (unguarded)
conversions from scalar number to BigInt, which is theoretically simple
but a bit fiddly.

[Please do not change anything below this line]
-----------------------------------------------------------------
---
Flags:
category=library
severity=low
---
Site configuration information for perl v5.8.3:

Configured by Debian Project at Sat Mar 27 17:07:14 EST 2004.

Summary of my perl5 (revision 5.0 version 8 subversion 3) configuration:
Platform:
osname=linux, osvers=2.4.25-ti1211, archname=i386-linux-thread-multi
uname='linux kosh 2.4.25-ti1211 #1 thu feb 19 18:20:12 est 2004 i686 gnulinux '
config_args='-Dusethreads -Duselargefiles -Dccflags=-DDEBIAN -Dcccdlflags=-fPIC -Darchname=i386-linux -Dprefix=/usr -Dprivlib=/usr/share/perl/5.8 -Darchlib=/usr/lib/perl/5.8 -Dvendorprefix=/usr -Dvendorlib=/usr/share/perl5 -Dvendorarch=/usr/lib/perl5 -Dsiteprefix=/usr/local -Dsitelib=/usr/local/share/perl/5.8.3 -Dsitearch=/usr/local/lib/perl/5.8.3 -Dman1dir=/usr/share/man/man1 -Dman3dir=/usr/share/man/man3 -Dsiteman1dir=/usr/local/man/man1 -Dsiteman3dir=/usr/local/man/man3 -Dman1ext=1 -Dman3ext=3perl -Dpager=/usr/bin/sensible-pager -Uafs -Ud_csh -Uusesfio -Uusenm -Duseshrplib -Dlibperl=libperl.so.5.8.3 -Dd_dosuid -des'
hint=recommended, useposix=true, d_sigaction=define
usethreads=define use5005threads=undef useithreads=define usemultiplicity=define
useperlio=define d_sfio=undef uselargefiles=define usesocks=undef
use64bitint=undef use64bitall=undef uselongdouble=undef
usemymalloc=n, bincompat5005=undef
Compiler:
cc='cc', ccflags ='-D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS -DDEBIAN -fno-strict-aliasing -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64',
optimize='-O3',
cppflags='-D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS -DDEBIAN -fno-strict-aliasing -I/usr/local/include'
ccversion='', gccversion='3.3.3 (Debian 20040314)', gccosandvers=''
intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=1234
d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=12
ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8
alignbytes=4, prototype=define
Linker and Libraries:
ld='cc', ldflags =' -L/usr/local/lib'
libpth=/usr/local/lib /lib /usr/lib
libs=-lgdbm -lgdbm_compat -ldb -ldl -lm -lpthread -lc -lcrypt
perllibs=-ldl -lm -lpthread -lc -lcrypt
libc=/lib/libc-2.3.2.so, so=so, useshrplib=true, libperl=libperl.so.5.8.3
gnulibc_version='2.3.2'
Dynamic Linking:
dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-rdynamic'
cccdlflags='-fPIC', lddlflags='-shared -L/usr/local/lib'

Locally applied patches:


---
@INC for perl v5.8.3:
/etc/perl
/usr/local/lib/perl/5.8.3
/usr/local/share/perl/5.8.3
/usr/lib/perl5
/usr/share/perl5
/usr/lib/perl/5.8
/usr/share/perl/5.8
/usr/local/lib/site_perl
.

---
Environment for perl v5.8.3:
HOME=/home/zefram
LANG (unset)
LANGUAGE (unset)
LD_LIBRARY_PATH (unset)
LOGDIR (unset)
PATH=/home/zefram/pub/i686-pc-linux-gnu/bin:/home/zefram/pub/common/bin:/usr/bin:/usr/X11R6/bin:/bin:/usr/local/bin:/usr/games:/opt/libunsn/bin
PERL_BADLANG (unset)
SHELL=/usr/bin/zsh


zefram at fysh

Apr 14, 2004, 1:59 PM

Post #2 of 10 (122 views)
Permalink
Re: [perl #28538] Math::BigInt doesn't grok "0 but true" [In reply to]

Incidentally, this bug is a duplicate of #28493. I screwed up in sending
the report. Since this one's seeing activity, someone please kill #28493.

Tels via RT wrote:
>I mean, if the variable represents "3" and "foo" at the same time, how is
>BigInt supposed to know which one is the *right* value? (The same goes for
>"3" and "5", which one is right?)

If you're treating it as a string -- which you are for validity testing
-- you should use the string slot. A dualvar simply has two different
values, and which value you get depends on what operation you subject
the value to. It's rarely correct to look at both slots, which is what
happened in the case I pointed out.

>One could also create an object that stringifies to something different than
>it numifies.. which would also confuse BigInt...

This is exactly the same issue.

If you want to be able to use a value as both a string and a number and
get consistent results, then do

$value = "$value";

or

$value = 0 + $value;

depending on which slot you want to take, to collapse it to an ordinary
value.

>Just to clarify, do you mean workaround in your code, or in BigInt?

I meant in my code. I had code that added together ordinary Perl
integers and BigInts, using +, expecting to get a correct BigInt result.
Now I write "(0+$a) + $b" instead of "$a + $b" (where $a is an ordinary
integer and $b is a BigInt), because $a is actually the return value of
a function that returns zero as "0 but true".

I can see why a string-based BigInt constructor is necessary, but (a)
please make it consistently use the string slot and (b) we should also
have a number-based constructor, consistently using the number slot.
I also propose that the implicit conversions in the overloaded operators
should be number-based rather than string-based, so that things that
look like they treat values as numbers will in fact do so.

-zefram


zefram at fysh

Apr 15, 2004, 1:36 AM

Post #3 of 10 (123 views)
Permalink
Re: [perl #28538] Math::BigInt doesn't grok "0 but true" [In reply to]

Hugo van der Sanden via RT wrote:
>It isn't quite as simple as that: I wouldn't call "00" a dualvar, even
>though it satisfies the above inequality.

I'd say that that *is* a dualvar, just one that's unlikely to be
a problem. I recall "00" used to be used where "0 but true" is now.
I accept 0+$val ne $val for the definition of a dualvar.

But we shouldn't need to ask whether something is a dualvar. It should
never matter. In any particular context a value should be treated
as either a number or a string. If we want to be able to use either,
we should have distinct operators, a la == and eq.

-zefram


yves.orton at de

Apr 15, 2004, 5:24 AM

Post #4 of 10 (123 views)
Permalink
RE: [perl #28538] Math::BigInt doesn't grok "0 but true" [In reply to]

> I'd say that that *is* a dualvar, just one that's unlikely to be
> a problem. I recall "00" used to be used where "0 but true" is now.
> I accept 0+$val ne $val for the definition of a dualvar.

Doesnt that make virtually every string a dualvar?

Yves


jpeacock at rowman

Apr 15, 2004, 8:23 AM

Post #5 of 10 (123 views)
Permalink
Re: [perl #28538] Math::BigInt doesn't grok "0 but true" [In reply to]

Orton, Yves wrote:

> Doesnt that make virtually every string a dualvar?

Not unless the string has been used in a numeric context before:

> $ perl -MDevel::Peek -e '$pv = "Test"; Dump $pv; $dv = 42; $dv = "HHGTTG"; Dump $dv;'
> SV = PV(0x804d5d8) at 0x806572c
> REFCNT = 1
> FLAGS = (POK,pPOK)
> PV = 0x805f240 "Test"\0
> CUR = 4
> LEN = 5
> SV = PVIV(0x804d9e8) at 0x80657a4
> REFCNT = 1
> FLAGS = (POK,pPOK)
> IV = 42
> PV = 0x805ede0 "HHGTTG"\0
> CUR = 6
> LEN = 7
>

John

--
John Peacock
Director of Information Research and Technology
Rowman & Littlefield Publishing Group
4501 Forbes Boulevard
Suite H
Lanham, MD 20706
301-459-3366 x.5010
fax 301-429-5748


yves.orton at de

Apr 15, 2004, 8:35 AM

Post #6 of 10 (124 views)
Permalink
RE: [perl #28538] Math::BigInt doesn't grok "0 but true" [In reply to]

> Orton, Yves wrote:
>
> > Doesnt that make virtually every string a dualvar?
>
> Not unless the string has been used in a numeric context before:
>
> > $ perl -MDevel::Peek -e '$pv = "Test"; Dump $pv; $dv = 42;
> $dv = "HHGTTG"; Dump $dv;'
> > SV = PV(0x804d5d8) at 0x806572c
> > REFCNT = 1
> > FLAGS = (POK,pPOK)
> > PV = 0x805f240 "Test"\0
> > CUR = 4
> > LEN = 5
> > SV = PVIV(0x804d9e8) at 0x80657a4
> > REFCNT = 1
> > FLAGS = (POK,pPOK)
> > IV = 42
> > PV = 0x805ede0 "HHGTTG"\0
> > CUR = 6
> > LEN = 7
> >

I meant WRT Zefram's definition:

0+$val ne $val

Which means that

0+"HHGTTG" ne "HHGTTG"

thus pretty much any string that matches \D (insert suitable handwaving
here) would be a dualvar based on his criteria.

Basically I was making this point as an addendum to Hugo saying that the
rules were more complicated than that.

Yves


jpeacock at rowman

Apr 15, 2004, 8:51 AM

Post #7 of 10 (123 views)
Permalink
Re: [perl #28538] Math::BigInt doesn't grok "0 but true" [In reply to]

Orton, Yves wrote:

> Basically I was making this point as an addendum to Hugo saying that the
> rules were more complicated than that.

Doh, yes of course you were. The actual definition should be symbolically more
like:

IV != (IV*)PV
and/or NV != (NV*)PV

where that cast stands in for the actual conversion of slots involved.

John

--
John Peacock
Director of Information Research and Technology
Rowman & Littlefield Publishing Group
4501 Forbes Boulevard
Suite H
Lanham, MD 20706
301-459-3366 x.5010
fax 301-429-5748


zefram at fysh

Apr 15, 2004, 9:45 AM

Post #8 of 10 (122 views)
Permalink
Re: [perl #28538] Math::BigInt doesn't grok "0 but true" [In reply to]

I still maintain that this discussion of identifying dualvars is
irrelevant to this bug report. But anyway, here's a function to play
with:

use warnings;
use strict;
use Scalar::Util qw(looks_like_number);

sub classify($) {
my($val) = @_;
# N.B.: domain: $val must be non-reference non-glob defined scalar
no warnings "numeric";
my $isnum = 0+$val eq $val;
my $isstr = "$val" == $val;
if($isnum && $isstr) {
print "both normal number and normal string\n";
} elsif($isnum) {
print "normal number, stringification is lossy\n";
} elsif($isstr) {
print "normal string, numerification is lossy\n";
} else {
print "must be a dualvar\n";
}
}

Try passing it the arguments

123
"123"
"0123"
12345678901234567890
dualvar(1, "1")
dualvar(1, "01")
dualvar(1, "foo")

This function classifies scalars based on whether they could have
originated as an ordinary number or an ordinary string, or whether they
could only exist as dualvars. "could have originated as an ordinary foo"
== "is accurately described by its foo part alone". Many values, such
as the small integers, could originate both ways. This only looks at
the current Perl-visible behaviour of the value, and can't say anything
about how it was actually created.

The test that I earlier endorsed as testing for dualvarness is in
fact the test used here that determines whether a value is accurately
described by its numeric part alone (i.e., a dualvar is not accurately
described by its numeric part alone). That's pretty much my instinctive
view of a dualvar -- and yes, this includes most ordinary strings -- but
then I'm thinking mostly from the point of view of numeric operations.
I find dualvarness to be a somewhat fuzzy concept.

Side discovery: Data::Dumper doesn't handle dualvars. It should probably
use something like the above code to decide whether to emit a dualvar()
call. I'll take this up in a separate bug report.

-zefram


doy at tozt

Apr 29, 2012, 11:26 AM

Post #9 of 10 (123 views)
Permalink
Re: [perl #28538] Math::BigInt doesn't grok "0 but true" [In reply to]

On Sun, Apr 29, 2012 at 11:01:25AM -0700, Father Chrysostomos via RT wrote:
> On Sun Apr 29 10:13:39 2012, Hugmeir wrote:
> > (Tangentially related, Data::Dumper still doesn't understand dualvars.
> > Nowadays, I imagine that to detect one of those you could use B to get
> > the flags, and check if it's both p?POK and p?[IN]OK)
>
> But that alone would bring up many false positives.
>
> I wouldn’t consider $x a dualvar after ‘$x = "3.0"; 0+$x’.

I think that just not looking at the p variants would fix that issue -
just look for things that are both POK and [IN]OK.

-doy


fraserbn at gmail

Apr 30, 2012, 1:09 AM

Post #10 of 10 (112 views)
Permalink
Re: [perl #28538] Math::BigInt doesn't grok "0 but true" [In reply to]

On Sun, Apr 29, 2012 at 4:29 PM, Father Chrysostomos via RT <
perlbug-followup [at] perl> wrote:

> On Sun Apr 29 11:27:06 2012, doy [at] tozt wrote:
> > On Sun, Apr 29, 2012 at 11:01:25AM -0700, Father Chrysostomos via RT
> wrote:
> > > On Sun Apr 29 10:13:39 2012, Hugmeir wrote:
> > > > (Tangentially related, Data::Dumper still doesn't understand
> dualvars.
> > > > Nowadays, I imagine that to detect one of those you could use B to
> get
> > > > the flags, and check if it's both p?POK and p?[IN]OK)
> > >
> > > But that alone would bring up many false positives.
> > >
> > > I wouldn’t consider $x a dualvar after ‘$x = "3.0"; 0+$x’.
> >
> > I think that just not looking at the p variants would fix that issue -
> > just look for things that are both POK and [IN]OK.
>
> Not so.
>
> $ perl5.15.9 -e '$x = "3.0"; 0+$x; use Devel::Peek; Dump $x'
> SV = PVNV(0x802340) at 0x822330
> REFCNT = 1
> FLAGS = (IOK,NOK,POK,pIOK,pNOK,pPOK)
> IV = 3
> NV = 3
> PV = 0x301580 "3.0"\0
> CUR = 3
> LEN = 16
>

Oh, my bad then. Guess that in the end you would have to check if the
contents of the PV slot differed from the [NI]V slot, which is pretty much
what the discussion in the ticket suggested. Doh!

Perl porters RSS feed   Index | Next | Previous | View Threaded
 
 


Interested in having your list archived? Contact Gossamer Threads
 
  Web Applications & Managed Hosting Powered by Gossamer Threads Inc.