views:

144

answers:

3

If a string in Perl 5 passes looks_like_number, it might as well be a number. For instance,

my $s = "10" + 5;

results in $s being assigned 15.

Are there any cases where a string does not behave like it's numeric equivalent would have?

+10  A: 

I can only think of one: when checking for truth. Strings that are equivalent to 0, but that are not "0", such as "0.0", "0 but true", "0e0", etc. all pass looks_like_number and evaluate to 0 in numeric context, but are still considered true values.

Chas. Owens
+9  A: 

An equivalent number and string behave differently in hash keys -- or, more generally, any time we stringify a largish number:

my (%g, %h);
$g{ 1234000000000000 } = undef;  # '1.234e+015'       => undef
$h{'1234000000000000'} = undef;  # '1234000000000000' => undef

Note that we are still within the range where Perl can store the number precisely:

> perl -e 'printf qq{%.f\n}, 1234000000000000 + $_ for +1, 0, -1'
1234000000000001
1234000000000000
1233999999999999
FM
I can't reproduce this on any of my systems; `perl -le '$h{1234000000000000} = 0; print keys %h'` spits out 1234000000000000. Could you post the results of this code on your system: `perl -MDevel::Peek -le '$n = 1234000000000000; $n . ""; Dump $n; print $]'`
Chas. Owens
@Chas. I'm running ActivePerl v5.10.0. I get the same behavior with Perl v5.8.8 on a Solaris machine too. Here's the output from your code, run on the Windows box, with semi-colons to indicate line breaks: `SV = PVNV(0x238e4c) at 0x182adb4; REFCNT = 1; FLAGS = (NOK,POK,pNOK,pPOK); IV = 0; NV = 1.234e+015; PV = 0x18351ec "1.234e+015"\0; CUR = 10; LEN = 36; 5.010000`.
FM
It seems that the machines I tested it on are 64 bit machines and the ones you tested it on are 32 bit machines (or at least 32 bit versions of `perl`).
Chas. Owens
That makes sense. Perl stringifies an IV as an integer, and an NV in `printf "%g"` format. On a 32-bit machine, 1234000000000000 lives in the twilight zone where it's too big for an int, but still small enough for exact integer representation as a double, so you don't *notice* it's not an int until you ask it to be a string.
hobbs
+15  A: 

When dealing with bitwise operators. 123 ^ 456 is 435, but "123" ^ "456" is "\x05\x07\x05". The bitwise operators work numerically if either operand is a number.

hobbs
Good point. Interestingly, if either operand is a number, the other operand is treated as a number: `perl -le 'print for "123" ^ 456, 123 ^ "456"'`
Chas. Owens
Thanks, corrected.
hobbs