Perlはスカラーを文字列または数値としてどのように扱うかを決定しますか?

StackOverflow https://stackoverflow.com/questions/330878

  •  11-07-2019
  •  | 
  •  

質問

次のコードとその出力を検討してください:

コード

#!/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;

ご覧のとおり、2番目の変数は文字列として扱われ、最初と4番目の変数は数字として扱われます。誰もが基礎となるロジックは何ですか?

編集追加された算術計算は、問題を完全には解決しません($ 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がその出力に基づいて内部的にデータを処理していることをあまり知ることができません。 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

他のヒント

変数を文字列または数値として扱うPerlの概念全体に欠陥があります。 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;
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top