PHP入門 代数演算子

算術演算子とも言います。四則演算をはじめ、日常的な数学で利用する演算子について解説します。

主な代数演算子

演算子概要
+数値の和5+4 = 9
数値の差6-3 = 3
*数値の積3*4 = 12
/数値の商15 / = 5
%数値の剰余13 % 3 = 1
**数値の累乗2 ** 3 = 8
++前置加算(代入前に加算)$x = 3;$y = ++$x; $yは4
++後置加算(代入前に加算)$x = 3;$y = $x++; $yは3
前置減算(代入前に減算)$x = 3;$y = –$x; $yは2
後置減算(代入前に減算)$x = 3;$y = $x–; $yは3

文字列混在の演算

代数演算子では、数値だけではなく文字列も演算できます。

文字列混在の演算ルールは、PHP8で大きく変換しました。

PHP8以前の挙動

<?php
print '108' + '15';       //結果:123   ➊
print '108' + '1.5XYZ';   //結果:109.5 ➋
print '108' + 'XYZ10';    //結果:108   ➌
print '108' + '1.5XYZ10'; //結果:109.5 ➍
print '108' + '1.5E1';    //結果:123   ➎
print '108' + '0B11';     //結果:108   ➏
print '108' + '010';      //結果:118   ➐
print '108' + '0X1A';     //結果:108   ➑

❶は、リテラルがクォート文字で囲まれているので、オペランドの108と15はいずれも文字列型の値です。しかし、代数演算子はこれを暗黙的に数値リテラルとみなして演算します。※❷❸❹も同様

❷のケースは、後続の不要な文字列を無視して演算します。

❸のように文字列が先頭に来る場合は、PHPはこれを認識できません。XYZ10は0とみなされます。

❺は数値/文字列混在ケースですが、指数表現とみなして計算されます。

❻❼❽のように2/8/16進数文字列を渡した場合、10進数には変換されず❷から❹と同様のルールで演算されます。

PHP8の挙動

PHP8でも先頭が数値で始まる文字列(❷❹❻❽)は数値として見なされますが、より厳しく「A non-numeric value encountered」のような警告が発生します。❸のように先頭が数字でない文字列については、「Unsupported operand types: string + string」のようなエラーとなります。

加算子(++)/減算子(–)

「++」と「–」は、与えられたオペランドに対して1を加算/減算するための演算子です。それぞれ加算子(インクリメント演算子)、減算子(デクリメント演算子)と言います。

$x = $x + 1 を $x++と表現できます。
$x = $x - 1 を $x--と表現できます。

加算子/減算子をオペランドの前後に置くかで挙動が変わります。加算子をオペランドの前方に置くことを「前置演算」、後方に置くことを「後置演算」といいます。

<?php
$x = 10;
$y = ++$x;
print $x;  //結果:11 
print $y;  //結果:11 ➊

$i = 10;
$j = $i++;
print $i;  //結果:11
print $j;  //結果:10 ➋
  • ❶の前置演算を行った場合は、加算子は変数$xへの加算を行ったあとで$yへの代入を行います。
  • ❷の後置演算では、加算子は変数$jへの代入を行ったあと、$iへの加算処理を行います。

マジカルインクリメント

アルファベットと数値が混在した文字列に対して加算子を適用すると、末尾がアルファベットであれば次の文字へ、数値であれば1を加算するという特殊な処理を行います。末尾の文字がZ(z)または9であった場合には、1つ前の文字に対して、桁の繰り上げを行います。英数字混在の連番コードを生成するときに便利な機能です。減算子を用いた、マジカルデクリメントのような機能はありません。

<?php
$i = 'Z';
print ++$i;  //結果:AA 
print ++$i;  //結果:AB 

$j = 'T8';
print ++$j;  //結果:T9
print ++$j;  //結果:U0

浮動小数点の演算の注意

floorは、小数点を切り捨てるための関数です。この場合、(0.1+0.7)×10=8なので、切り捨てても結果は8となるはずです。しかし、結果は7となります。これは、浮動小数点が内部的に2進数で演算されるために発生する誤差です。10進数ではごく単純に表せる0.1という値ですら、2進数の世界では、0.000110011001・・・という無限循環小数となります。結果として、7.999・・・となり正しい結果を得られません。

<?php
print floor((0.1+0.7) * 10);  //結果は7

この問題を避けるために、任意精度数学関数を利用します。任意精度数学関数では、bcadd(加算)、bcsub(減算)、bcmul(乗算)、bcdiv(除算)、bccomp(比較)をもって、演算を実施します。

<?php
$add = bcadd(0.1, 0.7, 1);   //➊
$mul = bcmul($add, 10, 1);
print floor($mul);           //結果は8

❶については、「0.1+0.7を小数点以下1桁まで計算しなさい」という意味になります。

配列の結合

加算演算子(+)は、配列の加算(結合)にも対応しています。加算演算子は、左の配列に存在しないキーの要素を右の配列から取り出し、左の配列に追加します。つまり、右の配列に左の配列と同じキーがあった場合、その値は無視されます。

通常配列の結合には「+」演算子ではなく、array_maerge命令を利用します。
<?php
$assoc1 = [
    'Apple' => 'Red',
    'Orange' => 'Yellow',
    'Melon' => 'Green'
];
$assoc2 = [
    'Grape' => 'Purple',
    'Apple' => 'Green',
    'Strawberry' => 'Red'
];
$result = $assoc1 + $assoc2;
print_r($result);

$ary1 = [1, 3, 5];
$ary2 = [2, 3, 6];
$result = $ary1 + $ary2;
print_r($result);
実行結果
実行結果