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

Hello,

I just want some advice on how to add a supposedly numeric value to a pre existing hash value.

For example,
at the moment in my hash could be a small value like e-149. I then want to add another value, say 2e-36, to the value that is already stored in the hash element, where e represents 2 x10-36 in the above example.

Is perl capable of realising that the string 2e-36 is in fact 2 x10-36?

If it is, can i add the new value to the old one? If not after converting it to a number can i stil add the element to the new value without it just concatenating the strings.

cheers, MonkPaul.

Replies are listed 'Best First'.
Re: Adding hash values together
by trammell (Priest) on Jun 30, 2005 at 17:30 UTC
    Seems to behave correctly for me:
    #!perl -l use strict; use warnings; my %hash; my $string = '2e-149'; $hash{foo} = 1e-149; print "\$hash{foo} = $hash{foo}"; $hash{foo} += $string; print "\$hash{foo} = $hash{foo}"; $string = '2e-36'; $hash{foo} += $string; print "\$hash{foo} = $hash{foo}"; __END__ $hash{foo} = 1e-149 $hash{foo} = 3e-149 $hash{foo} = 2e-36
Re: Adding hash values together
by ikegami (Patriarch) on Jun 30, 2005 at 17:46 UTC
    Hashes stringify keys, and uses string comparisons to compare keys. That means:
    $hash{20} = 1; # Same as $hash{'20'} = 1; $hash{2e1} = 2; # Same as $hash{'20'} = 2; $hash{'2e1'} = 3; # Same as $hash{'2e1'} = 3; $hash{'2E1'} = 4; # Same as $hash{'2E1'} = 4; $hash{0+'2e1'} = 5; # Same as $hash{'20'} = 5; $hash{0+'2E1'} = 6; # Same as $hash{'20'} = 6; # '2E1' => 4, '2e1' => 3, '20' => 6

    Update: Changed the wording in the comments to avoid further confusion.

      I dont really understand where you are coming from in your example: do you mean that the string literal can cause some over writing in the hash key or something completely different ???

      MonkPaul

        I meant that 20, 024, 0x14, 2e1 and 2E1 will all stringify to '20', and therefore are all equal when used as keys.

        However, '20', '024', '0x14', '2e1' and '2E1' are already strings, so they are all considered unequal if used as keys.

Re: Adding hash values together
by GrandFather (Saint) on Jun 30, 2005 at 23:24 UTC

    In general Perl has a philosophy of "Do what I mean" (DWIM). In the context of numbers and strings Perl converts numbers to strings in a string context and converts strings to numbers in a number context.

    What determines the context?

  • Hash keys are strings so are a string context
  • Hash values are either
  • arithmetic operators provide a number context
  • string operators (., cmp, eq, gt ...) provide a string context

    You can force a number context by using +0 and string by .'' (empty quoted string):

    my $NumericValue = "10" + 0; my $StringValue = 10 . '';

    Perl is Huffman encoded by design.
Re: Adding hash values together
by tlm (Prior) on Jul 02, 2005 at 15:23 UTC

    For starters, perl does not consider e-149 to be a numeric value, so I wll assume you meant 1e-149.

    Your question implies that perl would somehow distinguish between arithmetic on hash values and arithmetic on any other scalars, which is not the case. Whatever arithmetic works for $foo and $bar, or $foo[ 0 ] and $bar[ 0 ], works for $foo{ epsilon } and $bar{ epsilon }. In particular

    % perl -wle '$x = "1e-149"; print $x + "2e-149"' 3e-149 % perl -wle '$hash{ x } = "1e-149"; print $hash{ x } + "2e-149"' 3e-149 % perl -wle '$hash{ x } = "1e-149"; print $hash{ x } + "2e-36"' 2e-36
    ...as expected.

    Last thing is that by default1 perl never interprets + to mean string concatenation. (It has . for that.) This is true even when applied to string operands. In this case the strings get converted to numeric values and added. As shown in the one-liners above, if the strings make sense as numbers, the addition will make sense arithmetically. But even when the operands don't make sense as numbers, perl will be a sport about it and do something:

    % perl -wle 'print( "x" + "y" )' Argument "y" isn't numeric in addition (+) at -e line 1. Argument "x" isn't numeric in addition (+) at -e line 1. 0

    1I suppose one could overload + for a class to mean concatenation, but this is not default behavior.

    the lowliest monk