将字符串转换为浮点数

时间:2012-04-05 15:44:56

标签: perl

请问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 个答案:

答案 0 :(得分: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将其视为一个字符串的原因。

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

Argument "asdf" isn't numeric in numeric eq (==) at -e line 1.

答案 1 :(得分: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舍入到两位小数,但事实上它只是将$price增加0.005。我想你打算写

int($price * 100 + 0.5) / 100

但你也把价值放在sprintf这是另一种做同样事情的方法。

要么

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

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

但两者都是矫枉过正的!

答案 2 :(得分: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

比较的性质==或您的案例!=将参数转换为数字,无论它们是否为数字。

答案 3 :(得分:-3)

你没有做错任何事。 Perl在转储之前将其转换为字符串。要进行比较,请使用==!=进行数字比较,使用eqne进行字符串比较。 Perl根据需要转换为字符串和数字。

示例:

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

$VAR1 = '3.1415';