2005年04月08日

Round() 関数は四捨五入関数ではない

 知っている人は当たり前なネタですが、知らないと素通りしてそのままにしてしまいそうなネタです。

 多くの言語に Round() 関数が用意されていますが、これは四捨五入する関数ではなく、「丸め」る関数です。
 名前のまんま。

 実は私、最近まで「丸め」とは「四捨五入のコンピュータ系方言」くらいに思っていたのですが、実は違いました。もっと広い言葉です。
 まず、「丸め」とはある精度以下の数値情報を捨てる処理のことで、「四捨五入」を含みます。他に少なくとも切り上げ、切捨て、そして今回話題にする「偶数丸め」があります。(もっとあるかも知れません)

 「偶数丸め」は IEEE 754 で定められており、JIS や ISO にも同じ規定があります。
 多くの Round() 関数の挙動もこの IEEE 754 に則った「偶数丸め」です。

 「偶数丸め」は四捨五入とほぼ同一ですが、次の1点が違います。
 「丸め単位の丁度まんなかで、どっちつかずの場合は、偶数側を採用する」
 したがって、1.25 を 0.01 の位で丸めると 1.2 になり、1.35 は 1.4 になります。

 俗に、Bankers Rounding(銀行の丸め)と呼ばれている計算方法だそうで、処理による誤差が「四捨五入」と比べて小さくなります。
 中央にあって本来どちらに属すかは半々であるものを「常に五入」すれば、半々でなく「常に大きく」なってしまいます。
 ですから「偶数丸め」は「四捨五入」よりも処理による誤差が小さくなります。

 先ほど「丸め単位」という言葉を使ったのは、2 を単位とする「丸め」や 0.5 を単位とする「丸め」もありえるためです。
 「丸め」は「四捨五入」よりも広い概念を示す言葉なんですね(四捨五入だと常に1×(10のn乗)を単位とします)。


 私、学生の頃に一部の言語でこういう挙動を見て「バグか?まぁ所詮○○だしな」と某社への偏見にまみれた思い込みをしていました。

  Round() がこういう挙動をする言語で四捨五入を実現する方法も常套手段があって、
 1)四捨五入したい位が1の位になるよう、(10のn乗)をかける。
 2)四捨五入したい値が正の数だったら 0.5 を足す。負の数だったら 0.5 を引く。
 3)小数点以下を切り捨てる(Int関数やFloor関数など)
 4)1)で使った数字の逆数をかける。(桁数を元に戻す)
 という処理です。(キャストや変数の型による精度も要注意)

 VB.NET だと
移動単位 = (10 ^ 桁数)
If 数値 > 0 Then
数値 = Math.Floor((数値 * 移動単位) + 0.5) / 移動単位
Else
数値 = Math.Ceiling((数値 * 移動単位) - 0.5) / 移動単位
End If
ですね。

  Round() の挙動が、あれはあれで正しいというのはちょっと恥ずかしい驚きでした。

 会計システムを扱っていた事がありましたが、自分が開発に関わった範囲では丸め、四捨五入は偶々なかったからよかったですが。
 消費税も含めて、日本円の金額か数量っていう自然数だけを扱っていましたから。
 でもこれで私が為替レートなど丸めが絡む仕様書を書いたら、曖昧さを混入させてしまうところですね。危ない危ない。
posted by 市井賢児 at 2005年04月08日 02:18
| Comment(2) | TrackBack(5) | プログラミング


この記事へのコメント
OOXMLの規格書(ISO/IEC 29500-1)のROUNDのところを見ても何も書いてありませんでした。直しておきます。
Posted by 村田真 at 2015年05月20日 08:17
VBAの場合(偶数丸め)はOOXMLの規格書には定義はなく、セルに書くROUNDの場合(普通の四捨五入)はOOXMLの規格書に定義がありました。しかし、IEEE 754の規則Bを参照すべきでしょうね。
Posted by 村田真 at 2015年05月20日 08:58
コメントを書く
お名前:

メールアドレス:

ホームページアドレス:

コメント:

この記事へのTrackBack URL
http://blog.seesaa.jp/tb/2842259

[vb6]Round関数は「四捨五入をする関数」ではありません。
Excerpt: IEEE 754 ですねー。これを知らないデベロッパも多いと聞きます。VB6において、丸め関数は”INT”,”FIX”,”ROUND”があります。 このうち、”ROUND”は「最も近い偶数に丸める」..
Weblog: aspxの日記(ASP++ブログ) by Moo
Tracked: 2006-01-20 15:04

[ソフトウェア][Desigeon]丸め処理
Excerpt: 四捨五入の処理について。ゲーム(Desigeon)に絡めた話。 まず、ソフトウェアの世界でよく言われる「丸め処理」による四捨五入は、小学校の算数で習う「四捨五入」とは似て非なるものである(必ずしも一..
Weblog: 熊恭太郎雑記
Tracked: 2006-07-03 09:28

Round関数と四捨五入
Excerpt: 緒方典子氏(aka 「魔法使いの開発工房」のニキータさん)彼女の書籍「Acces...
Weblog: ぱそこん備忘録
Tracked: 2007-02-11 16:11

Round関数と四捨五入
Excerpt: 緒方典子氏(aka 「魔法使いの開発工房...
Weblog: 中小企業で働くパソコン相談係のお仕事
Tracked: 2007-06-28 14:10

桴瑰㨯⽷睷⹶慬牡猭灬慧攮湥琯硴牥浥⵮漯
Excerpt: 䥔R彔彞ケ 猀彟
Weblog: 桴瑰㨯⽷睷⹶慬牡猭灬慧攮湥琯硴牥浥⵮漯
Tracked: 2016-11-29 14:16
×

この広告は1年以上新しい記事の投稿がないブログに表示されております。