SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

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

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

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


  • X ポスト
  • このエントリーをはてなブックマークに追加

整数化

$ 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ページ オールカラー

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

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
USP MAGAZINEコラボレーション連載/「シェル芸」に効く AWK処方箋連載記事一覧

もっと読む

この記事の著者

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

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

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/8025 2017/01/31 20:03

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング