オークション事業部 プラットフォーム技術 後藤です。
私たちのチームはauctionリスト、サーチ、課金などのサービスの運用業務を
行っておりますが、今回は課金の検算などでよく利用するawkでの数値演算につ
いてレポートします。
消費税算出など小数点付きのものを四則演算する場合、awk(表示形式のデフォル
ト書式)を用いて生成する場合、以下ような現象が出ますので注意が必要です。
「7けた以上で科学表記になる場合がある」
「小数点を含めたけた数が7けた以上になると、誤差が出る場合がある」
などです。
以下の理屈が分かっていれば、なにも不思議はないのですが、結構誤差が出るパ
ターンも多いので、利用者の意識が必要なのだなーと思っています。
[awkの説明]
print 文を数値を出力するために使った場合、awkは内部で数値を (その数値を表す)文字列に変換し、
その文字列を出力する。 awkはこの変換動作のためにsprintf関数を使用する。
組込み変数のOFMTは、出力をおこなうときにprintがsprintf を使って数値を文字列に変換するための
書式のデフォルト設定を保持している。
OFMTのデフォルトの値は"%.6g"である。
CONVFMTのデフォルトの値は"%.6g"であり、これは値を最低6文字あるとして変換する。
awkではすべての数値は倍精度の浮動小数点数である。
最近のマシンの大部分では倍精度実数は十進数で16から17けたの精度がある。
Controlling Numeric Output with print抜粋
[sprintfの形式]
[表記説明]
科学表記は10のべき乗で表す
(浮動小数点表記はXXXXX.XXの形で表す)
[浮動小数点数型と誤差]
・表示形式による表記違い(計算結果が7けた以上の場合)
OFMTのデフォルトの値は"%.6g"ですので、科学表記か浮動小数点表記いずれかの出力になります。
表記はキャラクタ数が少なくなる方で出力されます。
・丸め誤差(近い整数に丸められる)
OFMTのデフォルトの値は"%.6g"ですので、小数点を含めたけた数が7けた以上
になると、誤差が出る場合があります。
(本来「11167.95」からの切り捨てデータとして「11167」を欲してますが、 近い整数に丸められています)
・表示形式による情報落ち(小さな値)
OFMTのデフォルトの値は"%.6g"ですので、6けた以下の情報は失われます。
(0.0000003333のデータは失われます)
・丸め誤差(小さな値の情報落ち)
絶対値が大きな値と小さな値とを加えた場合、小さい方の数値がもつ情報は失われます。
(0.03456のデータは失われます)
私たちのチームはauctionリスト、サーチ、課金などのサービスの運用業務を
行っておりますが、今回は課金の検算などでよく利用するawkでの数値演算につ
いてレポートします。
消費税算出など小数点付きのものを四則演算する場合、awk(表示形式のデフォル
ト書式)を用いて生成する場合、以下ような現象が出ますので注意が必要です。
「7けた以上で科学表記になる場合がある」
「小数点を含めたけた数が7けた以上になると、誤差が出る場合がある」
などです。
以下の理屈が分かっていれば、なにも不思議はないのですが、結構誤差が出るパ
ターンも多いので、利用者の意識が必要なのだなーと思っています。
[awkの説明]
print 文を数値を出力するために使った場合、awkは内部で数値を (その数値を表す)文字列に変換し、
その文字列を出力する。 awkはこの変換動作のためにsprintf関数を使用する。
組込み変数のOFMTは、出力をおこなうときにprintがsprintf を使って数値を文字列に変換するための
書式のデフォルト設定を保持している。
OFMTのデフォルトの値は"%.6g"である。
CONVFMTのデフォルトの値は"%.6g"であり、これは値を最低6文字あるとして変換する。
awkではすべての数値は倍精度の浮動小数点数である。
最近のマシンの大部分では倍精度実数は十進数で16から17けたの精度がある。
Controlling Numeric Output with print抜粋
[sprintfの形式]
"%.6g" 科学表記か浮動小数点表記の、いずれか出力するキャラクタ数が少なくなる方で出力する。
"%.6e" 数値を科学(または指数)形式で出力する。
"%.6f" 浮動小数点表記で小数点以下のけた数表示指定する。
[表記説明]
科学表記は10のべき乗で表す
echo ""|awk '{ OFMT = "%.6e"} {print 100000000000}'
結果:1.000000e+11(浮動小数点表記はXXXXX.XXの形で表す)
echo ""|awk '{ OFMT = "%.6f"} {print 100000000000}'
結果:100000000000.000000
[浮動小数点数型と誤差]
・表示形式による表記違い(計算結果が7けた以上の場合)
OFMTのデフォルトの値は"%.6g"ですので、科学表記か浮動小数点表記いずれかの出力になります。
表記はキャラクタ数が少なくなる方で出力されます。
echo "" | awk '{ OFMT = "%.6g"} {print 1815755+0.95 }'
結果:1.81576e+06・丸め誤差(近い整数に丸められる)
OFMTのデフォルトの値は"%.6g"ですので、小数点を含めたけた数が7けた以上
になると、誤差が出る場合があります。
echo "" | awk '{ OFMT = "%.6e"} {print 223359*0.05 }'
結果:11168(本来「11167.95」からの切り捨てデータとして「11167」を欲してますが、 近い整数に丸められています)
・表示形式による情報落ち(小さな値)
OFMTのデフォルトの値は"%.6g"ですので、6けた以下の情報は失われます。
echo "" | awk '{ OFMT = "%.6g"} {print 1/3 }'
結果:0.333333(0.0000003333のデータは失われます)
・丸め誤差(小さな値の情報落ち)
絶対値が大きな値と小さな値とを加えた場合、小さい方の数値がもつ情報は失われます。
echo "" | awk '{ OFMT = "%.6g"} {print 77777.7 + 1.23456}'
結果:77778.9(0.03456のデータは失われます)
こちらの記事のご感想を聞かせください。
- 学びがある
- わかりやすい
- 新しい視点
ご感想ありがとうございました