数値と文字列のための演算子

数値のための演算子

まずは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つ読み込み, それらを四則演算(+, -, *. /)した結果を出力するコードを書いてみましょう

例えば, 標準入力で12を入力した場合, 次のようになります:

1 + 2 = 3
1 - 2 = -1
1 * 2 = 2
1 / 2 = 0.5

results matching ""

    No results matching ""