2010年8月19日木曜日

数値から文字列にする時に、実数を7桁以上表示させる方法 - AWK

AWKの数値計算関数と関連機能
AWKにおける実数の表示は、有効数字6桁までに制限されています。
数値と文字列を並べて書く時や、数値から文字列に自動変換する時も、同様です。
でも、「今時の電卓は12桁です。6桁は少な過ぎます」と思った事はありませんか。

このような時、AWKでは、3つの方法を使う事が出来ます。


**** 手順
o 方法1. printfや sprintf関数を使って、変数を1つずつ変換する方法
o 方法2. 数値から文字列への自動変換規則を変更する方法
o 方法3. 計算方法を工夫する方法(= AWKの限界を超える方法)

** 方法1 printfや sprintf関数を使って、変数を1つずつ変換する方法
o 部分的に表示桁数を変更したい時に、便利です。
--------
printf("今日のラッキーナンバーは %.12g\n", 393393.393393);
または
v = sprintf("了解です。%.12g", 393393.393393);
--------


** 方法2. 数値から文字列への自動変換規則を変更する方法
o AWKは、文字列と並べて出力するだけでも、数値の表示桁数を6桁にしようとします。
o そこで、プログラムの先頭で、数値から文字列への自動変換に関する変数2つ(CONVFMTOFMT)の値を変更しておくと、変換の手間が少なくて済みます。

o 例えば、数値の最大表示桁数(及び、文字列に自動変換する時の最大桁数)を12桁に変更する場合
o 方法2-1。プログラムの最初で設定する方法
--------
BEGIN {
  CONVFMT = "%.12g";
  OFMT = "%.12g";
  #(以下、必要な処理)

  v1 = 123456.789012;
  v1 = v1 ""; # 文字列化。この時使う書式は、変数 CONVFMT
  print v1;

  v2 = 123456.789012;
  print v2; # 数値の出力。この時使う書式は、変数 OFMT
}
--------


o方法2-2。AWKプログラムを実行する時に設定する方法
   + 「 -v」オプションを使います。gawk以外も、書き方は同じです。
   + (Windowsのコマンドプロンプト画面では、「%」をAWKに渡したい時に「%%」と書きます。)
--------
gawk -v CONVFMT=%%.12g -v OFMT=%%.12g -f a.awk in.txt > out.txt
--------

o なお、AWKの数値計算時の有効数字は、最大15桁程度です(= 32ビットOS用にコンパイルした場合)。それよりも長く表示させても、あまり意味がありません。

o 一方、CONVFMTを使った方法が使えない場面もあります。それは、$0$1などの、「$ + 数字」の形になっている変数に入れる時、"%.6g"固定になる場面です。
   + mawkの場合は、$0に実数を直接入れる時だけ起こります。
   + Gawkやオリジナルは、$1、$2などに実数を入れる時も起こります。
   + 問題が起こる時は、一旦、他の変数に入れて文字列化し、その後で $1などに入れると、問題を回避出来ます。
--------
BEGIN {
  CONVFMT = "%.12g";
  OFMT = "%.12g";
}
{
  v = 123456.789012 ""; # 事前に、普通の変数に入れて文字列化します
  $1 = v; # $付きの変数に代入
}
--------



** 方法3.計算方法を工夫する方法(= AWKの限界を超える方法)
o 円周率を100桁以上表示したい時など、AWKの数値計算性能を超えている時は、計算方法を工夫する事で対応出来ます。
   + 整数演算を複数組み合わせて計算する手法があります。
   + 文字列のまま計算するという手法もあります。
   + 計算が遅い部分はC言語などに任せて、計算結果をAWKに(文字列の形で)読み込む、という方法もあります。
o このような用途の場合は、誰かが公開している部品を探してきて使う方が、早く出来そうな気がします。
   + 必要に応じて、部品を修正します。


==
関連ページ:
    ▼AWKの数値計算関数と関連機能▼ABC順
    ▼AWKプログラムを書く▼ABC順
    ▼AWK
    ▼制作メモ
    > AWKプログラムの中で、8進数や16進数を使う方法
    int = 実数や文字列を整数化する
    strtonum = 10進数、8進数、16進数の文字列を数値に変換する(Gawk専用)
    +
    数値計算関数使用時の注意点まとめ
    文字列操作関数使用時の注意点まとめ
(2010年9月22日追加。$1代入時の注意点で使用例)
(2010年9月8日追加。方法2が使えない場面と回避方法)
(2010年8月27日追加。方法2-1に出力例)