كيف يقرر بيرل التعامل مع العدد العددي كسلسلة أو رقم؟
سؤال
خذ بعين الاعتبار الكود التالي ومخرجاته:
شفرة
#!/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
المحلول
تتمثل مهمة Data::Dumper في إجراء تسلسل للبيانات ولا يمكنك معرفة الكثير عما يفعله Perl داخليًا بالبيانات بناءً على مخرجاته.ال ديفيل::نظرة خاطفة يمكن للوحدة النمطية تفريغ العلامات والقيم الأساسية المخزنة في المتغيرات.The 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
نصائح أخرى
إن مفهومك الكامل المتمثل في معاملة Perl للمتغيرات كسلاسل أو أرقام معيب.ستتعامل لغة Perl مع متغيراتك بالطريقة الصحيحة عندما تحتاج إليها، على سبيل المثال، العوامل الحسابية دائماً تعامل مع حجتهم كأرقام (بافتراض أنك لا تسيء استخدام التحميل الزائد للمشغل أو ما شابه).
لا يجب أن تقلق بشأن هذا:بيرل يعرف ما يفعله.
يستخدم Data::Dumper نمطًا بسيطًا في تمثيل السلسلة للمتغير لتحديد ما إذا كان رقمًا.من الكود المصدري:
...
elsif ($val =~ /^(?:0|-?[1-9]\d{0,8})\z/) { # safe decimal number
$out .= $val;
}
else { # string
...
لا يتطابق هذا مع الأرقام التي تحتوي على علامة عشرية تشرح السلوك الذي لاحظته.
طريقة قذرة سريعة لفرض سياق رقمي:
print Dumper( $HOURS_DURATION + 0.0 );
إذا كان اهتمامك هو كيفية عرض البيانات فإن الطريقة النظيفة هي:-
printf "%5.2d",$HOURS_DURATION;