How can a string with alpha chars in it be numerically equivalent to a number in Perl?

Viewed 55

Is it true that Perl numerically evaluates any string that starts with a number as numerically equivalent to that number (after warning that it is not numerical)?

I am trying to understand how the various comparison operators work. I wrote a script to output various TRUE or FALSE results as follows. (My question is posed afterward.)
(For my post I have condensed the curly braces into single lines, to save space and maybe make it easier to read.
This is my first question to StackOverflow, so if I can improve how my question was asked, or where to ask it, please let me know.)

#!/usr/bin/perl -w
#compOpers-mathyIn_TF.pl
use strict;

print "Enter expression to compare.\n";
chomp ( my $var = <STDIN> );

if ( $var == 0 ) { print "$var == 0 is TRUE.\n"; }
else { print "$var == 0 is FALSE.\n"; }
if ( $var == 1 ) { print "$var == 1 is TRUE.\n"; }
else { print "$var == 1 is FALSE.\n"; }
if ( $var eq "0" ) { print "$var eq \"0\" is TRUE.\n"; }
else { print "$var eq \"0\" is FALSE.\n"; }
if ( $var eq "1" ) { print "$var eq \"1\" is TRUE.\n"; }
else { print "$var eq \"1\" is FALSE.\n"; }

I tried this with some mathematical expressions such as "4 - 3" (and "4-3"), which didn't work. Sample output:

~\Perlscripts>perl compOpers_mathyInput_TF.pl
Enter expression to compare.
4 - 3
Argument "4 - 3" isn't numeric in numeric eq (==) at compOpers_mathyInput_TF.pl line 8, <STDIN> line 1.
4 - 3 == 0 is FALSE.
4 - 3 == 1 is FALSE.
4 - 3 eq "0" is FALSE.
4 - 3 eq "1" is FALSE.

~\Perlscripts>

After some research I realized that Perl will not mathematically parse this STDIN by default; once I added an eval function to the code as follows (done for each if block), it worked better.

if ( eval($var) == 0 ) { print "eval($var) == 0 is TRUE\.\n"; }
else { print "eval($var) == 0 is FALSE\.\n"; }

But before getting to that point, I had already received some puzzling results with my original code.
At first I thought the below result was mathematically parsing my input of "1 x 1", but that doesn't actually seem to be the case.

~\Perlscripts>perl compOpers_mathyInput_TF.pl
Enter expression to compare.
1 x 1
Argument "1 x 1" isn't numeric in numeric eq (==) at compOpers_mathyInput_TF.pl line 8, <STDIN> line 1.
1 x 1 == 0 is FALSE.
1 x 1 == 1 is TRUE.                   <<<-----
1 x 1 eq "0" is FALSE.
1 x 1 eq "1" is FALSE.

~\Perlscripts>

Here are other similar results where Perl is evaluating the second truth test in the script ( == 1 ) test to be TRUE, even though they are clearly not equal (along with a couple FALSE results too):

1 x 1 == 1 is TRUE.<br>
1/235 == 1 is TRUE.<br>
1x2 == 1 is TRUE.<br>
2x1 == 1 is FALSE.<br>
1andsometimes7 == 1 is TRUE.<br>
7isnt1 == 1 is FALSE.<br>

Question 1) From what I can see, Perl numerically evaluates any string that starts with a number as numerically equivalent to that number (after warning that it is not numerical).
Is this true? Is it a problem? Why does it work this way?

(I also tried setting the second truth test to match a different number than "1" (I used 8), and the results were the same.)

I also have a follow up question, a result that was somewhat surprising to me. Once I changed the script to use eval, the numerical comparisons worked as expected. But the string comparison also came up true here:

~\Perlscripts>perl compOpers_eval-mathyInput_TF.pl
Enter first expression to compare.
4-3
eval(4-3) == 0 is FALSE.
eval(4-3) == 1 is TRUE.
eval(4-3) eq "0" is FALSE.
eval(4-3) eq "1" is TRUE.                   <<<-----

~\Perlscripts>

**Question 2**
(mainly just asking for confirmation) `"4-3"` is obviously not the same characters as in the string `"1"`.
Am I correct that the `eval()` parses my input, evaluates it mathematically, and the result is then essentially placed into a string, `"1"`, which is exactly the same characters as the comparison string `"1"`?
1 Answers

Perl's a bit weird because it's the operators that coerce the data rather than the data deciding what the operators do. Since Perl has a scalar instead of a more specific data type, it figures out if you wants strings or numbers based on what you are doing. If you use numeric operators, Perl will try to convert the operands to numbers.

It does this by ignoring leading whitespace, they taking the decimal digits up to the end of the string or the first non-decimal digit. It will also accept the first decimal point and the decimal digits that follow it. We cover this in Learning Perl, but you can also read about it in perlnumber.

So, the string 4 - 1 is numerically 4, with a warning:

$ perl -wle " print q(4 - 1) + 0 "
Argument "4 - 1" isn't numeric in addition (+) at -e line 1.
4

I think you're asking a slightly different question. Perl does not do math for you. You have an eval in there, and that will execute the string as Perl code. What the Perl code evaluates to is what you get back.

Related