3

soemone 可以帮我解决以下情况吗?我正在尝试比较 $price 和 $lsec。

if( (sprintf("%.2f", ($price*100+0.5)/100)*1 != $lsec*1) )
{
                print Dumper($price,$lsec)
}

有时,倾销者会打印相同的数字(作为字符串)并跳进去。想,乘以 1 会使它们产生浮点数......

这里自卸车输出:

$VAR1 = '8.5';
$VAR2 = '8.5';

我究竟做错了什么?

谢谢,

问候和复活节快乐。

4

4 回答 4

4

Perl 变量中存储的内容与使用方式之间存在差异。您是正确的,乘以 1 会强制将变量用作数字。它还导致将数字存储在SV向解释器表示变量的数据结构中。您可以使用该Devel::Peek模块查看 Perl 存储在每个变量中的内容:

use Devel::Peek;
my $num = "8.5";
Dump $num;

输出:

SV = PV(0xa0a46d8) at 0xa0c3f08
  REFCNT = 1
  FLAGS = (POK,pPOK)
  PV = 0xa0be8c8 "8.5"\0
  CUR = 3
  LEN = 4

继续……

my $newnum = $num * 1;
Dump $num;
Dump $newnum;

输出:

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

我们关心的属性是PV(字符串指针)、NV(浮点数)和IV(整数)。最初,$num只有字符串值,但将其用作数字(例如在乘法中)会导致它存储数值。但是,$num仍然“记住”它是一个字符串,这就是为什么Data::Dumper将它视为一个字符串。

对于大多数目的,不需要显式强制将字符串用作数字,因为运算符和函数可以以最合适的形式使用它们。==例如, and运算符将!=其操作数强制转换为数字形式以进行数字比较。使用eqorne代替强制进行字符串比较。这是始终use warnings在您的 Perl 脚本中的另一个原因,因为尝试将非数字字符串与 进行比较==将获得以下警告:

Argument "asdf" isn't numeric in numeric eq (==) at -e line 1.
于 2012-04-05T16:41:22.187 回答
3

你说对一个字符串乘以 1 会强制它被评估为一个数字是正确的,但是数字!=比较器会做同样的事情。这大概是您从其他语言中获得的一种技术,因为 Perl 通常会做正确的事情,并且不需要强制转换任一操作数。

让我们看一下您要比较的值:

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);
}

输出

8.51 <=> 8.5
$VAR1 = '8.5';
$VAR2 = '8.5';

所以 Perl 正确地说 8.51 不等于 8.5。

我怀疑你的

($price * 100 + 0.5) / 100

旨在四舍五入$price到小数点后两位,但实际上它所做的只是增加$price0.005。我想你是想写

int($price * 100 + 0.5) / 100

但是您也可以通过sprintf它来做同样的事情的另一种方式。

任何一个

$price = int($price * 100 + 0.5) / 100

或者

$price = sprintf ".2f", $price

但两者都是矫枉过正!

于 2012-04-05T18:16:21.280 回答
1

这部分:

($price*100+0.5)/100)

如果你输入 8.5,你会得到 8.505。这自然不等于8.5。由于您没有更改$price,因此您不会注意到任何差异。

Perl 会自动处理转换,因此您无需担心这一点。

my $x = "8.5";
my $y = 8.5;
print "Equal" if $x == $y; # Succeeds

比较的性质,==或者在您的情况下!=将参数转换为数字,无论它们是否为数字。

于 2012-04-05T15:58:16.390 回答
-3

你没有做错什么。Perl 在转储之前将其转换为字符串。对于比较,使用==and!=进行数字比较和eq字符串ne比较。Perl 根据需要转换为字符串和数字。

例子:

$ perl -MData::Dumper -e "my $a=3.1415; print Dumper($a);"

$VAR1 = '3.1415';

于 2012-04-05T15:49:45.667 回答