<Lua> Luaにおける算術演算子

Last modified: 2019-07-21

ここではLuaにおける算術演算子についてを扱う。

解説

算術演算子とは

算術演算子とはプログラム内で数値の演算(足し算や引き算など)を行う際に用いる記号のことで

[変数もしくは定数1] [算術演算子] [変数もしくは定数2] ([算術演算子] [変数もしくは定数3] ...)

の形で用いられる。

例としては “1 + 2” の “+” が足し算をするための算術演算子となり

a = 1 + 2

という文を記述すると、変数aに計算結果の “3” が入ることになる。

Luaで利用可能な算術演算子の一覧

Luaでは以下の算術演算子が利用できる。

演算子 はたらき
+ 左の値と右の値を足した結果を得る [足し算/加算]
- 左の値から右の値を引いた結果を得る [引き算/減算]
* 左の値と右の値を掛けた結果を得る [掛け算/乗算]
/ 左の値を右の値で割った結果を得る [割り算/除算]
% 左の値を右の値で割った余りを得る [割り算の余り/剰余演算]
^ 左の値を右の値の回数(1未満や負の値も可)繰り返し掛けた結果を得る [累乗の計算/指数演算]

算術演算子の優先順位

算数演算子には優先順位があり、1 + 2 * 3のように複数の演算が行われる形の記述においては、左から順番に計算するのではなく、どこが先に計算されるかのルールが決まっている。

優先順位は

  • 高: ^ (累乗の計算)
  • 中: *, /, % (掛け算や割り算)
  • 低: +, - (足し算や引き算)

となるが、これは強く意識しなくても数学での計算と同様と考えればよい。

例えば、 “1 + 2 x 3 + 22 / 4 “という計算は最初に累乗の計算で “1 + 2 x 3 + 4 / 4” となって次に掛け算・割り算で “1 + 6 + 1” となり、最後にこれらを足したものが計算される。

$ lua -e "print(1 + 2 * 3 + 2 ^ 2 / 4)"
8

数学での計算と同様、もし先に計算したい部分があればそこを丸括弧で囲めばよい(優先順位の最も高い “累乗の計算” よりも優先される)。上の最初の “1 + 2” をまとまりとして “(1 + 2) x 3 + 22 / 4” とする計算を考えると “3 x 3 + 22 / 4” から “3 x 3 + 4 / 4” となって “9 + 1” が計算される。

$ lua -e "print((1 + 2) * 3 + 2 ^ 2 / 4)"
10

割り算についてのメモとC言語との比較

割り算の結果と商

Luaでは、/の演算子で割り算を行うと割り切れない場合に小数点以下が含まれる

$ lua -e "print(30000 / 1001)"
29.97002997003

整数の割り算で小数点以下(割り切れない部分)を切り捨て、”商”を得るには、/を用いた演算結果をmath.floor()という関数(引数の値以下の最大の整数を得る関数)に渡した戻り値を得る。

$ lua -e "print(math.floor(30000 / 1001))"
29

なお、C言語で整数型どうしの割り算を行った場合はこちらの動作となる。

小数点以下のある値における余りの計算

%演算子については、C言語の場合は整数型でしか使えないので小数点以下のある値で余りの計算をしたい場合はfmod()系の関数を呼ぶ必要があるが、Luaの場合は演算子の左右どちらについても小数点以下のある値が使える

$ lua -e "print(3.14 % 1.1)"
0.94

0で割ろうとした場合の動作と演算結果

Luaでは、割り算において0で割ろうとした場合、そこでエラーの類が発生したりプログラムが異常終了したりすることはなく、演算の結果としてinfという特殊な値が得られる。

$ lua -e "print(1 / 0)"
inf

C言語では “0で割る” 操作を行うプログラムをコンパイルすると警告が発生し、実行すると “floating point exception (core dumped)” などと表示されて落ちることがある。

符号の反転

-[半角スペース][変数もしくは定数]

と記述すると、 “-[半角スペース]” の右の変数もしくは定数の符号を逆にしたものが得られる。

$ lua -e "print(- -123)"
123
$ lua -e "a = 123; print(- a)"
-123

累乗の計算

2 ^ 3は “2を3回掛けたもの” だが、指数部分(^の右の値)は負の値や小数点以下のある値にもできる。

負の指数

“3を2回掛けた数で1を割った数” は3 ^ -2と表現できる。

$ lua -e "print(3 ^ -2)"
0.11111111111111

当然、これと “3を2回掛けた数” を掛けると “1” になる。

$ lua -e "print(3 ^ -2 * 3 ^ 2)"
1

これを指数法則を用いて書き換えると

$ lua -e "print(3 ^ (-2 + 2))"
1

となるが、指数部分が “0” になる場合は^の左側の値に関わらず “1” が得られる。

累乗根

“12回掛けると2になる値(2の12乗根)” は2 ^ (1 / 12)と表現できる。

$ lua -e "print(2 ^ (1 / 12))"
1.0594630943593

当然、これを12回掛けると “2” になる。

$ lua -e "print((2 ^ (1 / 12)) ^ 12)"
2

指数法則を用いて書き換えると

$ lua -e "print(2 ^ ((1 / 12) * 12))"
2

となるが、指数部分が “1” になる場合は^の左側の値と同じ値が得られる。

平方根(2回掛けるとその数になる値)を計算する場合は指数部分を “1 / 2” の値となる “0.5” にする。例えば、 “ルート2” の値は2 ^ 0.5として計算できる。

$ lua -e "print(2 ^ 0.5)"
1.4142135623731

変数の値の加算などの記述について

プログラムを記述する言語によっては[変数]++[変数] += [増加値]といった記述による変数値の加算などの操作ができるようになっているが、Luaではこのような書き方はできない。

$ lua -e "i = 0; i++"
lua: (command line):1: syntax error near '+'

$ lua -e "i = 0; i += 1"
lua: (command line):1: syntax error near '+'

できるのは、その変数の値を含んだ値を新しい値として代入する形([変数] = [変数] [算術演算子] [値]形式)のみ。

$ lua -e "i = 0; i = i + 1; print(i)"
1

コード例

下のコードは算術演算子の使用例となる。

[任意]ファイル名:005_arithmetic_operators.lua

#! /usr/bin/lua
-- -*- coding: utf-8 -*-

--[[--  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --
動作確認バージョン: 5.3, JIT2.1
--  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --]]

-----
----- 算術演算子の使用例
-----

do
    -- 足し算
    print(('1 + 2 + 3 = %d'):format(1 + 2 + 3))

    -- 引き算
    print(('5 - 8 = %d'):format(5 - 8))

    -- 掛け算
    print(('111 * 222 = %d'):format(111 * 222))

    -- 割り算と余り計算
    -- 割った結果(小数点以下含む・商はmath.floor()に入れた結果)
    local x = 55 / 12
    -- 余り
    local y = 55 % 12
    -- 余りを「%」演算子を使わずに計算すると下のコメントのようになる
    --local y = 55 - math.floor (55 / 12) * 12
    -- 「%s」はformat()による書式変換なしの状態で表示できる
    -- (「%f」などでは小数点以下の表示が変わる場合がある)
    print(('55 / 12 = %f (%s) = %d ... %d'):format(x, x, math.floor(x), y))
    -- 0で割ると「inf」という特殊な値になる(プログラムの実行は終了しない)
    print(('5 / 0 = %f'):format(5 / 0))

    -- 累乗と累乗根
    -- 2の10乗(2を10回掛けた数)
    print(('2 ^ 10 = %d'):format(2 ^ 10))
    -- 2の-3乗(1を「2を3回掛けた数」で割った数・「2の3乗」分の1)
    print(('2 ^ -3 = %f (%s)'):format(2 ^ -3, 2 ^ -3))
    -- 2の平方根(2回掛けると2になる数・ルート2)
    print(('2 ^ (1 / 2) = %.10f'):format(2 ^ (1 / 2)))
    -- 2の12乗根(12回掛けると2になる数)
    print(('2 ^ (1 / 12) = %.10f'):format(2 ^ (1 / 12)))

    -- 「-」は符号を反転させる
    local a = 7
    local b = - a
    local c = - b
    local d = - c
    print(('%d --> %d --> %d --> %d'):format(a, b, c, d))

    -- 表示区切り
    print(('-'):rep(80))

    -- 変数の値の加算など
    -- 「[変数]++ (1加算)」や「[変数] += [値] (右の値を加算)」といった記述は不可
    -- 「[変数] = [変数] [算術演算子] [演算する値]」形式で記述する
    local i = 1; print('> i = 1')
    print(('i = %d'):format(i))
    i = i + 1; print('> i = i + 1')
    print(('i = %d'):format(i))
    i = i - 10; print('> i = i - 10')
    print(('i = %d'):format(i))
end

-- 終了

下は実行結果。

$ lua [005_arithmetic_operators.luaの場所]
1 + 2 + 3 = 6
5 - 8 = -3
111 * 222 = 24642
55 / 12 = 4.583333 (4.5833333333333) = 4 ... 7
5 / 0 = inf
2 ^ 10 = 1024
2 ^ -3 = 0.125000 (0.125)
2 ^ (1 / 2) = 1.4142135624
2 ^ (1 / 12) = 1.0594630944
7 --> -7 --> 7 --> -7
--------------------------------------------------------------------------------
> i = 1
i = 1
> i = i + 1
i = 2
> i = i - 10
i = -8
  • 使用したバージョン
    • Lua 5.3.3
    • LuaJIT 2.1.0 Beta 3