Reputation: 623
could soemone help me with the following condition, please? I'm trying to compare $price and $lsec.
if( (sprintf("%.2f", ($price*100+0.5)/100)*1 != $lsec*1) )
{
print Dumper($price,$lsec)
}
Sometimes the dumper prints same numbers(as strings) and jumps in. Thought, that multiplying with 1 makes floats from them...
Here dumper output:
$VAR1 = '8.5';
$VAR2 = '8.5';
What am I doing wrong?
Thank you,
Greetings and happy easter.
Upvotes: 4
Views: 13349
Reputation: 126722
You are correct to say that multiplying a string by 1 will force it to be evaluated as a number, but the numeric !=
comparator will do the same thing. This is presumably a technique you have acquired from other languages as Perl will generally do the right thing and there is no need to force a cast of either operand.
Lets take a look at the values you're comparing:
use strict;
use warnings;
use Data::Dumper;
my $price = '8.5';
my $lsec = '8.5';
my $rounded_price = sprintf("%.2f", ($price * 100 + 0.5) / 100);
print "$rounded_price <=> $lsec\n";
if ( $rounded_price != $lsec ) {
print Dumper($price,$lsec);
}
output
8.51 <=> 8.5
$VAR1 = '8.5';
$VAR2 = '8.5';
So Perl is correctly saying that 8.51 is unequal to 8.5.
I suspect that your
($price * 100 + 0.5) / 100
is intended to round $price
to two decimal places, but all it does in fact is to increase $price
by 0.005. I think you meant to write
int($price * 100 + 0.5) / 100
but you also put the value through sprintf
which is another way to do the same thing.
Either
$price = int($price * 100 + 0.5) / 100
or
$price = sprintf ".2f", $price
but both is overkill!
Upvotes: 4
Reputation: 5995
There is a difference between what is stored in a Perl variable and how it is used. You are correct that multiplying by 1 forces a variable to be used as a number. It also causes the number to be stored in the SV
data structure that represents the variable to the interpreter. You can use the Devel::Peek
module to see what Perl has stored in each variable:
use Devel::Peek;
my $num = "8.5";
Dump $num;
outputs:
SV = PV(0xa0a46d8) at 0xa0c3f08
REFCNT = 1
FLAGS = (POK,pPOK)
PV = 0xa0be8c8 "8.5"\0
CUR = 3
LEN = 4
continuing...
my $newnum = $num * 1;
Dump $num;
Dump $newnum;
outputs:
SV = PVNV(0xa0a46d8) at 0xa0c3f08
REFCNT = 1
FLAGS = (PADMY,NOK,POK,pIOK,pNOK,pPOK)
IV = 8
NV = 8.5
PV = 0xa0be8c8 "8.5"\0
CUR = 3
LEN = 4
SV = NV(0x9523660) at 0x950df20
REFCNT = 1
FLAGS = (PADMY,NOK,pNOK)
NV = 8.5
The attributes we are concerned with are PV
(string pointer), NV
(floating-point number), and IV
(integer). Initially, $num
only has the string value, but using it as a number (e.g. in multiplication) causes it to store the numeric values. However, $num
still "remembers" that it is a string, which is why Data::Dumper
treats it like one.
For most purposes, there is no need to explicitly force the use of a string as a number, since operators and functions can use them in the most appropriate form. The ==
and !=
operators, for example, coerce their operands into numeric form to do numeric comparison. Using eq
or ne
instead forces a string comparison. This is one more reason to always use warnings
in your Perl scripts, since trying to compare a non-numeric string with ==
will garner this warning:
Argument "asdf" isn't numeric in numeric eq (==) at -e line 1.
Upvotes: 5
Reputation: 67900
This part:
($price*100+0.5)/100)
If you put in 8.5, you get back 8.505. Which naturally is not equal to 8.5. Since you do not change $price
, you do not notice any difference.
Perl handles conversion automatically, so you do not need to worry about that.
my $x = "8.5";
my $y = 8.5;
print "Equal" if $x == $y; # Succeeds
The nature of the comparison, ==
or in your case !=
converts the arguments to numeric, whether they are numeric or not.
Upvotes: 1
Reputation: 6824
You're doing nothing wrong. Perl converts it to a string before dumping it. For comparisons, use ==
and !=
for numeric comparisons and eq
and ne
for a string comparisons. Perl converts to strings and numbers as needed.
Example:
$ perl -MData::Dumper -e "my $a=3.1415; print Dumper($a);"
$VAR1 = '3.1415';
Upvotes: -3