CodeZine(コードジン)

特集ページ一覧

シェルで表計算ができるかも!? AWKの四則演算と数値演算関数

► 「シェル芸」に効く AWK処方箋 第5回 (月刊『USP MAGAZINE 2014 August (Vol.16)』より転載)

  • LINEで送る
  • このエントリーをはてなブックマークに追加
2014/08/27 14:00

目次

整数化

$ awk 'BEGIN {print int(1.5)}'
1

 AWKには整数部を表示する関数int()があります。

 ところで、AWKには「あって当然」の四捨五入を行う関数がありません。正の数に関して四捨五入は、次のようにすることで計算できます。

$ awk 'BEGIN {a = 1.5; print int(a + 0.5)}'
2

 ネット上の記事で、printf文で四捨五入する、という類いの記事を見かけることがあります。これは誤りですので注意してください。printf文には四捨五入のような機能はありません。次の例を見てください。

$ awk 'BEGIN{printf("%.2f\n", 110.115)}'
110.11
$ gawk 'BEGIN{printf("%.2f\n", 110.1151)}'
110.12

 printf文にはどのように丸めて表示するかは定められていないため、上記のような変な結果が返っても文句を言えないことになります。

 四捨五入などの処理を行うには必ず、その処理を記載するようにしてください。ただし、gawkの最新版では、printf文の丸めをどうするかについて設定できるようになっています。

問題

 では、ここで皆さんに問題です。次の結果はどうなるでしょうか。

$ awk 'BEGIN {print int(70.21 * 100)}'

 int()関数の引数を計算すると7021なので、7021と思われるかもしれませんが、答えは7020です。

$ awk 'BEGIN {print int(70.21 * 100)}'
7020

 詳細な説明は割愛しますが、70.21は2進数では表現できない数値のため、AWKの中では70.2099999999……として格納されています。そのため、7020となってしまうのです。ところが、この70.21という数値だけが特殊というわけではありません。2進数で計算しているプログラム言語においては10進数で小数点を表現できない場合があるため、この数値以外に同様のケースは存在します。十分に注意してください。

 また、AWKに限らず、他の言語でも同様な現象が起こりえるので注意しましょう。例えば、Perlでも同様の結果になります。

$ perl -e 'print int(70.21 * 100) . "\n"'
7020

 小数での比較演算子を用いる場合には特に、その境界で正しいふるまいをしているかどうかを確認した上で、比較演算を行うようにしましょう。思わぬところに落とし穴があるかもしれません。

どこまで計算できるのか

 では AWKはどこまで(何ビットまで)計算できるのでしょうか。次のプログラムで簡単に調べることができます。まずmawk(マイク・ブレナン氏が実装した拡張版AWK)です。

$ mawk 'BEGIN{printf("%d\n", 2 ^ 31 - 1)}'
2147483647
$ mawk 'BEGIN{printf("%d\n", 2 ^ 32 - 1)}'
2147483647

 「2 ^ 31 - 1」と「2 ^ 32 - 1」が同じ結果になっていますね。つまり、mawkは31ビットまでの計算ができます。一方、nawk(new AWK)やgawkの場合には、もっと上の桁まで計算できます。

$ nawk 'BEGIN{printf("%d\n", 2 ^ 53 - 1)}'
9007199254740991
$ nawk 'BEGIN{printf("%d\n", 2 ^ 54 - 1)}'
18014398509481984
$ gawk 'BEGIN{printf("%d\n", 2 ^ 53 - 1)}'
9007199254740991
$ gawk 'BEGIN{printf("%d\n", 2 ^ 54 - 1)}'
18014398509481984

 なんとなく正しい値を出しているように見えますが、右端の桁に注目してください。2のN乗は必ず偶数になりますから、2のN乗から1を引いた数は、必ず奇数になるはずです。ところが「2 ^ 54 - 1」は偶数になっており、正しく計算できていません。つまり、nawkとgawkは53ビットまで計算できることになります。

 さて、数値計算のために準備されているAWKの関数は、このように必要最小限のものです。他の言語のように、過剰に関数が準備されていないため覚えやすい一方、データが膨大になった場合でも適切に処理できるため、Excelの代わりに用いられることもあるでしょう。Excelのように様々な関数が準備されていると、うれしい場合もありますが、組込関数が覚えられず、リファレンスとにらめっこをすることになります。

 AWKの実装のため、srand()やatan2()関数、int()関数のように変わった振る舞いをするものもありますが、実際のプログラムでお目にかかることは少ないでしょう。遭遇する機会があれば思い出してください。

 なお、gawkはデフォルトでMPFR(Multiple Precision Floating-Point Reliable)による任意精度計算をサポートし、53ビット以上の計算も簡単に行えます。そのため、数値計算でAWKが活躍する場面も増えましたが、こちらについては機会があれば説明したいと思います。

『USP MAGAZINE 2014 September(Vol.17)』は、ただいま絶賛発売中!
USP MAGAZINE 2014 September(Vol.17)

 『USP MAGAZINE』は日本で唯一のシェルスクリプト総合誌(毎月25日発売)。最新号 2014 September(Vol.17)の巻頭は「軽量言語(LL)特集」! LLの歴史や各LLの特徴を「FIGHTING TALKS」でお馴染み法林さんがわかりやすく解説。もちろん、FIGHITNG TALKSも引き続き連載中です! さらに、6月26日に開催された各種軽量言語イベントの実行委員長達が集まったTechLION vol.17再録も収録。LLの魅力を詰め込みました。熊野憲辰さんの「未来に活きる!現場で使える!データモデリング」ではデータマネジメントについて解説。モデリングだけではなくデータの品質も重要なのです。他、好評連載中の「ユニケージエンジニアの作法」やAWK処方箋第6回なども掲載です!

 

► お求めは、Amazon.co.jpUSP研究所のWebサイト取り扱い書店まで。

 

USP MAGAZINE 2014 September(Vol.17)

価格:500円+税

仕様:B5版 64ページ オールカラー

発行人:ユニバーサル・シェル・プログラミング研究所



  • LINEで送る
  • このエントリーをはてなブックマークに追加

バックナンバー

連載:USP MAGAZINEコラボレーション連載/「シェル芸」に効く AWK処方箋

著者プロフィール

  • 斉藤 博文(サイトウヒロフミ)

    最初にAWKと出会ってから○十年、AWKの魅力に取りつかれ、勢い余って「日本 GNU AWKユーザー会」を立ち上げています。会としてOSCなどのイベントにも出展しつつ、GNU AWKの開発も手伝っています。「USP友の会」では幹事役ですが、「シェル芸勉強会」にはほぼ毎回参加して一緒に勉強しています。...

あなたにオススメ

All contents copyright © 2005-2021 Shoeisha Co., Ltd. All rights reserved. ver.1.5