数値と文字列のための演算子
数値のための演算子
まずはPerlで利用可能な, 数値に対する演算子を見ていきましょう. これらの演算子を使うことで, 変数に格納された数値に対して, 様々な計算を行うことができます.
use strict;
use warnings;
my $foo = 4;
my $bar = 2;
my $sum = $foo + $bar; # 4 + 2 = 6
my $sub = $foo - $bar; # 4 - 2 = 2
my $mul = $foo * $bar; # 4 * 2 = 8
my $div = $foo / $bar; # 4 / 2 = 2
my $mod = $foo % $bar; # 4 % 2 = 0
my $exp = $foo ** $bar; # 4の2乗は 16
このコードでは, 2つの変数$foo
と$bar
に数値を代入し, それらを使って+
演算子で加算(足し算), -
演算子で減算(引き算), *
演算子で乗算(掛け算), /
で除算(割り算), %
演算子で剰余(左辺を右辺で割った余り), **
演算子で冪乗(べき乗, 左辺の数値の右辺の数値乗)を計算しています.
なお, これらの演算子のうち, /
演算子と%
演算子については, 右辺の値(割る値)を0にすると, 実行時にエラーとなります.
use strict;
use warnings;
my $div = 1 / 0;
このコードの実行結果は, 次の通りです.
Illegal division by zero at prog.pl line 4.
また, 変数に格納された数値を, 1ずつ増やしたい/減らしたいときは, インクリメント/デクリメントという演算子を利用することができます.
(1)のように, 変数の後ろにインクリメント演算子(++
)を書くと, その変数に格納された数値が1増えます.
同様に, (2)のように, 変数の後ろにデクリメント演算子(--
)を書くと, その変数に格納された数値が1減ります.
use strict;
use warnings;
my $foo = 4;
$foo++; # (1) $fooをインクリメント
print $foo; # => 5
$foo--; # (2) $fooをデクリメント
print $foo; # => 4
文字列のための演算子
続いて, Perlで利用可能な, 文字列に対する演算子を見ていきましょう.
use strict;
use warnings;
my $foo = 'foo';
my $bar = 'bar';
my $baz = 1;
print $foo . $bar; # => foobar (1)
print $foo . 'oof'; # => foooof (2)
print $foo . $baz; # => foo1 (3)
print $foo . "\n"; # => foo\n (4)
print $foo . $bar . $baz; # => foobar1 (5)
my $string = $foo . $bar; (1')
まずは, 文字列を連結する.
演算子です. Perlで文字列を出力するとき, 非常によく利用する演算子です.
.
演算子を使えば, (1)
や(2)
のように, 変数に格納された文字列や, 文字列を自由に連結することができます.
もちろん, (1')
のように, 連結した文字列を変数に代入することも可能です.
前述したように, Perlでは数値を文字列としてそのまま利用することができます. そのため, (3)のように, 文字列が代入された変数($foo
)と, 数値が代入された変数($baz
)を, .
で連結することが出来ます. この場合, $foo
に格納されたfoo
と, $baz
に格納された1
が連結された, foo1
という文字列を得ることができます.
変数を出力する際, 末尾に改行を付与したい時は, (5)
のように書くことが出来ます. .
演算子を使って, 変数$foo
と改行を表す\n
を連結しています.
最後に, (5)
のように.
演算子を複数回使って, 複数の変数や文字列を一気に連結することも可能です.
use strict;
use warnings;
my $foo = 'foo' x 3;
print $foo; # => foofoofoo
次に紹介するのは, 文字列を任意の回数繰り返すx
です.
例えば上記のコードは, foo
という文字列を3回繰り返した文字列, つまりfoofoofoo
という文字列を, 変数$foo
に代入しています.
演算の順番
演算子を使って変数などを操作するとき, その優先順位について気をつける必要があります.
数学で, ( ... )
を使って演算の順序を指定できるように, Perlでも( ... )
を使って演算の順序を変更することができます.
use strict;
use warnings;
my $foo = 2 + 4 * 3; # => 14 (1)
my $bar = (2 + 4) * 3; # => 18 (2)
四則演算に関する演算子の優先順序は, 基本的に一般的な数学と同じ(加算, 減算よりも乗算, 除算を先に行う)です.
(1)
は先に4 * 3
の計算が行われ, その後に2
が足されるので, 計算結果は14
になりますが, (2)
では(2 + 4)
で, この足し算を先に行うように指定しているので, 結果として6 * 3
が計算され, 計算結果は18
になります.
よくある間違い: 数値の演算と文字列連結
use strict;
use warnings;
my $now = 2018;
print "Last year it was " . $now - 1 . ". Now it is " . $now;
このコードは, 変数$now
に代入した年(今年は2018年です)を利用して, 去年の年と, 今年の年を出力するコードです.
Last year it was 2017. Now it is 2018
という出力を期待したいところですが, 実際にこのコードを実行すると, 次のような警告が表示され, 更に出力は-1. Now it is 2018
となってしまっています.
Argument "Last year it was 2018" isn't numeric in subtraction (-) at prog.pl line 6.
-1. Now it is 2018
これは何故でしょうか? ...結論から述べると, .
と-
の演算の優先順位が, Perlにおいては同じだからです.
演算子の優先順位が同じ場合, Perlはその演算子が「左結合」か「右結合」かによって, どちらを先に実行するかを定めます.
.
と-
, そして+
の演算子は優先順位が同じで, 左結合の演算子となっています.
そのため, このコードを実行すると, $now - 1
ではなく, 先に一番左側にあるLast year it was
という文字列と変数$now
の連結を行い, その結果であるLast year it was 2018
という文字列から, 1
を引くという順序で計算を行います.
この時Perlは, Last year it was 2018
という文字列を, (先程示したように, 警告は表示するものの)無理矢理数値として解釈して計算を行い, コードの処理を継続します.
Last year it was 2017
を数値として解釈すると, Perlでは0
になるので, 0 - 1
すなわち-1
が表示されていたというわけです.
これを防ぐには, 次のコードのように, $now - 1
を( ... )
で囲い, 先に計算させるという方法があります.
use strict;
use warnings;
my $now = 2018;
print "Last year it was " . ($now - 1) . ". Now it is " . $now . "\n";
また, 次のように, 先に1年前の年を計算しておくという方法もあります.
use strict;
use warnings;
my $now = 2018;
my $last_year = $now - 1;
print "Last year it was " . $last_year . ". Now it is " . $now . "\n";
なお, 演算子の優先順位や, 左結合か右結合かなどについては, Perldocのperlop
に記載されています(英語 / 日本語).
練習問題 2-4
標準入力から0以外の整数を2つ読み込み, それらを四則演算(+
, -
, *
. /
)した結果を出力するコードを書いてみましょう
例えば, 標準入力で1
と2
を入力した場合, 次のようになります:
1 + 2 = 3
1 - 2 = -1
1 * 2 = 2
1 / 2 = 0.5