Perl如何决定将标量视为字符串或数字?

时间:2008-12-01 13:42:46

标签: perl string numbers scalar

考虑以下代码及其输出:

代码

#!/usr/bin/perl -w
use strict;
use Data::Dumper;
my $HOURS_PER_DAY = 24.0 * 1.0;
my $BSA = 1.7 * 1.0;
my $MCG_PER_MG = 1000.0 * 1.0;
my $HOURS_DURATION    = 20.0 * $HOURS_PER_DAY;
my $dummy = $HOURS_PER_DAY * $BSA * $MCG_PER_MG * $HOURS_DURATION;
print Dumper($HOURS_PER_DAY);
print Dumper( $BSA);
print Dumper( $MCG_PER_MG);
print Dumper( $HOURS_DURATION );

输出

$VAR1 = 24;
$VAR1 = '1.7';
$VAR1 = 1000;
$VAR1 = 480;

如您所见,第二个变量被视为字符串,而第一个和第四个变量被视为数字。任何人都知道底层逻辑是什么?

添加的

编辑算术计算无法完全解决问题(请参阅$ BSA变量)。


$ perl -v

This is perl, v5.10.0 built for cygwin-thread-multi-64int
(with 6 registered patches, see perl -V for more detail)

Copyright 1987-2007, Larry Wall

4 个答案:

答案 0 :(得分:7)

Data :: Dumper的工作是对数据进行序列化,你无法根据输出的数据来分析perl在内部做什么。 Devel::Peek模块可以转储存储在变量中的基础标志和值。 Devel :: Peek POD解释了旗帜的重要性。

#!/usr/bin/perl

use warnings;
use strict;
use Devel::Peek;

my $HOURS_PER_DAY = 24.0 * 1.0;
my $BSA = 1.7 * 1.0;
my $MCG_PER_MG = 1000.0 * 1.0;
my $HOURS_DURATION    = 20.0 * $HOURS_PER_DAY;
my $dummy = $HOURS_PER_DAY * $BSA * $MCG_PER_MG * $HOURS_DURATION;

Dump($HOURS_PER_DAY);
Dump($BSA);
Dump($MCG_PER_MG);
Dump($HOURS_DURATION);

__END__
SV = PVNV(0xd71ff0) at 0xd87f90
  REFCNT = 1
  FLAGS = (PADBUSY,PADMY,IOK,NOK,pIOK,pNOK)
  IV = 24
  NV = 24
  PV = 0
SV = PVNV(0xd71fc8) at 0xd87f60
  REFCNT = 1
  FLAGS = (PADBUSY,PADMY,NOK,pIOK,pNOK)
  IV = 1
  NV = 1.7
  PV = 0
SV = PVNV(0xd72040) at 0xd87f40
  REFCNT = 1
  FLAGS = (PADBUSY,PADMY,IOK,NOK,pIOK,pNOK)
  IV = 1000
  NV = 1000
  PV = 0
SV = IV(0xd8b408) at 0xd87f30
  REFCNT = 1
  FLAGS = (PADBUSY,PADMY,IOK,pIOK)
  IV = 480
# compare the above output to output without the assignment to $dummy:
SV = IV(0x7b0eb8) at 0x7adf90
  REFCNT = 1
  FLAGS = (PADBUSY,PADMY,IOK,pIOK)
  IV = 24
SV = NV(0x7c7c90) at 0x7adf60
  REFCNT = 1
  FLAGS = (PADBUSY,PADMY,NOK,pNOK)
  NV = 1.7
SV = IV(0x7b13d8) at 0x7adf40
  REFCNT = 1
  FLAGS = (PADBUSY,PADMY,IOK,pIOK)
  IV = 1000
SV = IV(0x7b1408) at 0x7adf30
  REFCNT = 1
  FLAGS = (PADBUSY,PADMY,IOK,pIOK)
  IV = 480

答案 1 :(得分:6)

Perl将变量视为字符串或数字的整个概念存在缺陷。当你需要它时,Perl会以正确的方式处理你的变量,例如,算术运算符总是将它们的参数视为数字(假设你没有滥用运算符重载或某些此类)。

你不应该担心这个:Perl知道它在做什么。

答案 2 :(得分:5)

Data :: Dumper在变量的字符串表示上使用简单模式来确定它是否是数字。来自源代码:

...
elsif ($val =~ /^(?:0|-?[1-9]\d{0,8})\z/) { # safe decimal number
  $out .= $val;
}
else {               # string
...

这与具有小数点的数字不匹配,这可以解释您观察到的行为。

答案 3 :(得分:0)

强制数字上下文的快速脏方法:

print Dumper( $HOURS_DURATION + 0.0 );

如果您关心的是如何显示数据,那么干净的方式是: -

printf "%5.2d",$HOURS_DURATION;