LoginSignup
6
4

More than 5 years have passed since last update.

UbuntuとTiny Core Linuxのシェルで計算してみる

Last updated at Posted at 2017-04-14

シェルで計算した時のメモです。Ubuntu16とTiny Core LinuxのCoreのインストール直後(と思う)状態で試しています。ここでいう標準シェルとはUbuntuならbash、Tiny Core Linuxならashを想定しています。

まずは整数の計算

exprコマンドで計算することができます。

exprコマンドを計算
$ echo $(expr 1 + 2)
3

$(())でも計算できます。

$(())で計算
$ echo $((1 + 2))
3

Tiny Core Linuxでの注意点

Tiny Core Linuxで$(())を使う際は書き方に注意が必要のようです。以下はマイナスの数値を引き算する例ですが、書き方によってはarithmetic syntax errorになってしまうようです。

TinyCoreLinuxでマイナス計算
$ a=1;b=-2
$ echo $(($a-$b))
-sh: arithmetic syntax error
$ echo $(($a - $b))
3
$ echo $((a-b))
3

また10桁を超えたあたりから結果がおかしくなるようです。Tiny Core Linuxで10桁を超える場合はexprコマンドを使う必要がありそうです。

TinyCoreLinuxで11桁の数値を計算
$ echo $(expr 12345678901 + 2)
12345678903
$ echo $((12345678901 + 2))
2

実数は使えません

残念ながらexpr$(())も小数点を含むとエラーになります。これはUbuntuでもTiny Core Linuxでも同じです。

$ echo $(expr 1.5 + 2)
expr: non-integer argument
$ echo $((1.5 + 2))
bash: 1.5 + 2: syntax error: invalid arithmetic operator (error token is ".5 + 2")

小数点を含んだもののも計算

bcコマンド

bcコマンドを使えば小数点を含む数値も計算できます。Tiny Core LinuxのCoreと呼ばれる最小構成の素の状態にはbcコマンドは含まれませんので、この方法はTiny Core LinuxのCoreでは使えません。※もちろんbcパッケージをインストールすれば使えます。

bcコマンド
$ echo $(echo '1.5 + 2' | bc)
3.5

-lオプションをつければsin、cos関数も使えます。

bcコマンドでsinとcos関数を使う
$ echo $(echo "s(80*3.14/180)" | bc -l)
.98468459013058331641
$ echo $(echo "c(80*3.14/180)" | bc -l)
.17434522637389628631

awkコマンド

awkコマンドのprintは計算式をサポートているだけでなく、小数点を含んだ数値もsin、cosといった関数も使えて、Tiny Core Linuxでも使えます。

awkコマンドで計算
$ echo $(echo '1.5 2' | awk '{print $1 + $2}')
3.5
awkコマンドでsinとcos関数を使う
$ echo $(echo "80" | awk '{print sin($1*3.14/180)}')
0.984685
$ echo $(echo "80" | awk '{print cos($1*3.14/180)}')
0.174345

awkの場合入力が必要なんですが、以下のようにヌル文字を渡せば計算式がそのまま書けます。個人的にはechoで値を渡す方が関数ぽく書けて好きですが…

awkコマンドでsinとcos関数を使う(2)
$ echo $(echo "" | awk '{print sin(80*3.14/180)}')
0.984685
$ echo $(echo "" | awk '{print cos(80*3.14/180)}')
0.174345

実行速度の違い

簡単なスクリプトを作って実行速度を測ってみました。

テスト Ubuntu16 TinyCoreLinux v7
整数(expr) 0.168544sec 0.133583sec
整数($(())) 0.00392652sec 0.00325775sec
整数(bc) 0.255331sec error
整数(awk) 0.228399sec 0.20771sec
実数(bc) 0.269739sec error
実数(awk) 0.230662sec 0.205647sec
関数(bc) 0.32672sec error
関数(awk) 0.230426sec 0.209495sec

結果として整数の場合ならexprよりも$(())の方が速くて、実数の場合ならbcコマンドよりawkコマンドの方が速いようです。
整数計算が10桁以下なら$(())、10桁を超えるならexpr、実数計算ならawkコマンドを使うようにすればUbuntuでもTiny Core Linuxでも良い結果が出そうです。

速度測定スクリプトのソース

以下が今回使用した速度測定スクリプトです。このスクリプトではナノ秒を取得するためにdateコマンドの%Nを使っているのですが、Tiny Core Linux v8では%Nが使えないようですのでv8では使えません。

速度測定スクリプト
#!/bin/sh
int_expr() {
  a=0
  for i in $(seq 0 99);do
    a=$(expr $a + $i)
  done
  echo $a
}

int_brackets() {
  a=0
  for i in $(seq 0 99);do
    a=$(($a + $i))
  done
  echo $a
}
int_bc() {
  a=0
  for i in $(seq 0 99);do
    a=$(echo "$a + $i" | bc)
  done
  echo $a
}
int_awk() {
  a=0
  for i in $(seq 0 99);do
    a=$(echo "$a $i" | awk '{print $1+$2}')
  done
  echo $a
}
real_bc() {
  a=0
  for i in $(seq 0 99);do
    a=$(echo "$a+$i*0.5" | bc -l)
  done
  echo $a
}
real_awk() {
  a=0
  for i in $(seq 0 99);do
    a=$(echo "$a $i" | awk '{print $1+$2*0.5}')
  done
  echo $a
}
func_bc() {
  a=0
  for i in $(seq 0 99);do
    a=$(echo "$a+s($i*3.14/180)+c($i*3.14/180)" | bc -l)
  done
  echo $a
}
func_awk() {
  a=0
  for i in $(seq 0 99);do
    a=$(echo "$a $i" | awk '{print $1+sin($2*3.14/180)+cos($2*3.14/180)}')
  done
  echo $a
}
set_time() {
    start_time=$(date +'%s.%N')
}
echo_time() {
    end_time=$(date +'%s.%N')
    echo $(echo "$start_time $end_time"|awk '{print $2-$1}')'sec'
}
set_time;int_expr;echo_time
set_time;int_brackets;echo_time
set_time;int_bc;echo_time
set_time;int_awk;echo_time
set_time;real_bc;echo_time
set_time;real_awk;echo_time
set_time;func_bc;echo_time
set_time;func_awk;echo_time

6
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
4