Beefy Boxes and Bandwidth Generously Provided by pair Networks
P is for Practical
 
PerlMonks  

Need some wisdom on strings to numbers

by decebel (Acolyte)
on Oct 07, 2009 at 02:08 UTC ( [id://799634]=perlquestion: print w/replies, xml ) Need Help??

decebel has asked for the wisdom of the Perl Monks concerning the following question:

Hello Monks,

Here I come again to seek some wisdom on a minor issue that has been bothering me since this afternoon. Basically, I have 2 variables and I am converting them to numbers:

my $store = {}; my $numString1 = '123'; my $num1 = $numString1+0; $store->{'num1'}=$num1; my $numString2 = '123.10'; my $num2 = $numString2+0; $store->{'num2'}=$num2; print Dumper $store;

Below is the output from the print Dumper statement:

{ 'num1' => 123, 'num2' => '123.1' };

As you can see, variable num1 gets converted to a number but num2 is not. num2 value 123.1 is surrounded in quotes and remains as a string.

As a second part of the question, what is an easy way to check if a string is a number and are there any standard ways to convert them to numbers

Thanks a lot in advance, Dece

Replies are listed 'Best First'.
Re: Need some wisdom on strings to numbers
by almut (Canon) on Oct 07, 2009 at 02:26 UTC

    This seems to be a weird artifact of Data::Dumper's processing:

    #!/usr/bin/perl use Data::Dumper; use Devel::Peek; my $store = {}; my $numString2 = '123.10'; my $num2 = $numString2+0; Dump $num2; #1 $store->{'num2'}=$num2; Dump $store->{'num2'}; #2 print Dumper $store; #3 Dump $store->{'num2'}; #4 __END__ SV = NV(0x636e40) at 0x604fd0 #1 REFCNT = 1 FLAGS = (PADBUSY,PADMY,NOK,pNOK) NV = 123.1 SV = NV(0x636e50) at 0x604410 #2 REFCNT = 1 FLAGS = (NOK,pNOK) NV = 123.1 $VAR1 = { #3 'num2' => '123.1' }; SV = PVNV(0x6b42f8) at 0x604410 #4 REFCNT = 1 FLAGS = (NOK,POK,pNOK,pPOK) IV = 0 NV = 123.1 PV = 0x6eb260 "123.1"\0 <-- side effect of dumping it with Data::D +umper CUR = 5 LEN = 40

    As you can see in Devel::Peek's output, $num2 initially is a number only (no PV), but after dumping it with Data::Dumper, the string representation has been added to the scalar. And apparently, Data::Dumper then also prefers the string representation for its output...

      swampyankee asked whether I would consider this a bug to be filed against Data::Dumper.  As I have no decided opinion on the matter, I'd like to pass the question on to all of you...   Essentially, I see two issues:

      (1) Data::Dumper promises

      (...) The return value can be "eval"ed to get back an identical copy of the original reference structure.

      However:

      use Data::Dumper; use Devel::Peek; my $foo = { num => 123.1 }; Dump $foo->{num}; my $serialised = Dumper $foo; $foo = eval $serialised; # deserialise Dump $foo->{num}; __END__ SV = NV(0x669d40) at 0x63c430 REFCNT = 1 FLAGS = (NOK,pNOK) NV = 123.1 <-- originally, it's a number SV = PV(0x63d918) at 0x742c80 REFCNT = 1 FLAGS = (POK,pPOK) PV = 0x6650d0 "123.1"\0 <- it's a string now, when deserialised... CUR = 5 LEN = 8

      But what would you consider "identical"...? I.e. does internal representation really matter, as Perl would automagically convert under most circumstances, anyway?

      (2) It's not exactly good manners to silently modify data structures under the hood, when being passed them just for dumping purposes (this could cause unexpected issues with copy-on-write semantics with forked processes — such as when trying to preload libs/data to be shared across processes, in order to keep memory usage low (mod_perl comes to mind...)).  OTOH, this is not the only case in Perl where such things do happen...

      So, whuttaya think?

        Personally, I would consider silently modifying data structures to be a bug. I realize there may be reasons for Data::Dumper treating floats as strings, mostly because Perl relies on the math library used by the C compiler used to build Perl's executable, and it may be distracting to see 123.1 show up as 123.09999… in Data::Dumper's output. The most obvious fix is to modify the documentation ("Data::Dumper outputs all floating point values as strings so that 123.1 doesn't appear as 123.0999…"). This has the obvious advantage of avoiding the need to change any code.


        Information about American English usage here and here. Floating point issues? Please read this before posting. — emc

Re: Need some wisdom on strings to numbers
by alexlc (Beadle) on Oct 07, 2009 at 03:13 UTC

    Edit: almut beat me to it. Thats what I get for walking the dogs mid-post.

    A couple of things...

    First, it probably should not matter to you whether something is a 'string' or a 'number', as internally perl will convert it between strings and numbers as needed. The only use case I can think of for needing to care is if you are passing things to a serialization routine, where the output is destined for another programming language where it matters.

    Second, I'm not sure I'd take the output of Data::Dumper at face value. Since from perl's perspective 123.1 is more or less the same as '123.1', it may just display the string.

    If you really care to see the internal representation of a perl variable, you can use Devel::Peek.

    use Devel::Peek qw| Dump |; my $x = 123.1; my $y = '123.10'; my $z = $y + 0; Dump $x; Dump $y; Dump $z;

    Outputs

    SV = NV(0x81ac10) at 0x801794 REFCNT = 1 FLAGS = (PADBUSY,PADMY,NOK,pNOK) NV = 123.1 SV = PVNV(0x8044d0) at 0x801770 REFCNT = 1 FLAGS = (PADBUSY,PADMY,NOK,POK,pIOK,pNOK,pPOK) IV = 123 NV = 123.1 PV = 0x301200 "123.10"\0 CUR = 6 LEN = 8 SV = NV(0x81ac20) at 0x801788 REFCNT = 1 FLAGS = (PADBUSY,PADMY,NOK,pNOK) NV = 123.1

    So, as you can see, $x and $z are strictly NVs ( numeric values ) while $y is a PVNV, which has both numeric and string values contained. More information on the 'c' types for perl variables can be found in perlguts.

    -- AlexLC
      Hi there,

      Thanks all for the prompt reply. I am passing the hash to an in-memory database (MongoDB) which serializes the hash into a json style structure. This causes the first variable (123) to remain as an int but the second one 123.1 gets in as a string and I think this is because the hash stores this value as a string. Any suggestions?

        As an afterthought to Alex's reply, is there a work around when we are serializing the data structure?
Re: Need some wisdom on strings to numbers
by ikegami (Patriarch) on Oct 07, 2009 at 04:17 UTC

    num2 value 123.1 is surrounded in quotes and remains as a string.

    Yes it is surrounded by quotes. No, it's not a string. Data::Dumper just seems to like to add quotes to floats.

    It doesn't matter. Perl switches between string and number on need.

Re: Need some wisdom on strings to numbers
by biohisham (Priest) on Oct 07, 2009 at 10:28 UTC
    "what is an easy way to check if a string is a number"

    This is an easy way to check if a scalar is a number or a string, the fact that &nding a number to its complement (or exclusive ORing of a scalar to itslef using the binary ^ operator) would give you zero if the scalar has a number can be a good distinction. However, there are some catches you have to be aware of, read How to check if a scalar value is numeric or string? for a wholesome discussion on this with examples included.


    Excellence is an Endeavor of Persistence. Chance Favors a Prepared Mind.
Re: Need some wisdom on strings to numbers
by llancet (Friar) on Oct 07, 2009 at 02:29 UTC
    It seems that perl actually always store numbers in string representation. Is that right? Waiting for answers...
      No
      use Devel::Peek; $_=123; Dump $_; # IOK ''.$_; Dump $_; # IOK+POK $_.=''; Dump $_; # POK 0+$_; Dump $_; # IOK+POK $_+=0; Dump $_; # IOK

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://799634]
Approved by ww
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others having a coffee break in the Monastery: (5)
As of 2024-04-19 10:28 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found