10

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 its numeric equivalent would?

Eran
  • 387,369
  • 54
  • 702
  • 768
Chas. Owens
  • 64,182
  • 22
  • 135
  • 226

4 Answers4

16

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
  • 223,387
  • 19
  • 210
  • 288
  • 2
    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 Jun 05 '10 at 14:57
11

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
  • 64,182
  • 22
  • 135
  • 226
10

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
FMc
  • 41,963
  • 13
  • 79
  • 132
  • 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 Jun 05 '10 at 15:05
  • @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`. – FMc Jun 05 '10 at 15:15
  • 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 Jun 05 '10 at 16:27
  • 3
    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 Jun 06 '10 at 04:05
2
  DB<1> sub is_num { my $x = shift; "$x " ~~ $x }

  DB<2> print is_num(123)
1
  DB<3> print is_num('123')

  DB<4> 
abufct
  • 71
  • 4