言いたいこと

Perl5.8以降であればScalar::Utilの「looks_like_numer」を使えば良いです。

数字かどうか判別したい

Perl入学式でもよく質問されました。 特に数値かどうかを判定したい、というのが多かったように思います。

「未定義」を計算させてみる

初期化されていない変数は未定義の状態になっています。

例えばこんな感じで未定義の変数を引き算すると、

1
2
3
4
5
6
7
8
#!/usr/bin/env perl
use strict;
use warnings;

my $x;
my $y;

print $x - $y;

こんな警告が出ます。

1
2
3
Use of uninitialized value $y in subtraction (-) at warnings.pl line 8.
Use of uninitialized value $x in subtraction (-) at warnings.pl line 8.
0

今の場合、未定義の変数を「0」として扱っているので、計算結果としては「0 - 0」となり、表示は「0」になります。

しかし、「use warnings」をしていると、未定義の変数を引き算しようとしてますよ、という警告がでます。

文字列を計算させてみる

また、文字列を計算しようとしても警告が出ます。

1
2
3
4
5
6
7
8
#!/usr/bin/env perl
use strict;
use warnings;

my $x;
my $y = '1e';

print $x - $y;

この場合、以下の様な警告がでます。

1
2
3
Argument "1e" isn't numeric in subtraction (-) at warnings.pl line 8.
Use of uninitialized value $x in subtraction (-) at warnings.pl line 8.
-1

この例の場合は「1e」を「1」として計算していますが、「1e」は数字じゃない、という警告が出ています。

何が問題か

コードの中で代入する場合はこのような問題は起きないと思います。

しかし、サブルーチンで渡される引数やユーザーからの入力が適切かどうかはわかりませんので、思わぬエラーを防ぐためにも想定している値なのかを確認しておくのが良いでしょう。

相手(今の場合はユーザーやサブルーチンを使う側)がどのような行動をするのかを見守るだけでなく、プログラム側から正しい入力を求めるようにする姿勢も大事ではないでしょうか?

looks_like_numberで判定する

Perlのバージョン5.8以降であれば、Scalar::Utilが標準で使えるのでlooks_like_numberを使うと数値の判定が簡単です。

コードを見てもわかりやすくて良いですね。

以下のプログラムは、数値を入力するまで終了しません。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#!/usr/bin/env perl
use strict;
use warnings;
use Scalar::Util qw(looks_like_number);

my $x;
while (1) {
print "数値を入力してください >>> ";
$x = <STDIN>;
chomp $x;
last if want_number($x);
}
print qq{入力された数値は `$x` です};
exit;

sub want_number {
my ($args) = @_;
return 1 if looks_like_number($args);
print "エラー:数値ではありません!\n";
return;
}

このプログラムで定義したwant_numberは渡された値が数値であれば真、数値でなければ偽を返します。

数値を判定するならlooks_like_numberを使おう

looks_like_numberに限らず、Perlには標準モジュールにも便利なものがあるので、積極的に使うと良いと思います。