端数処理
[Wikipedia|▼Menu]
シャープ Compet CS-2122L上の丸めセレクタ。左のツマミで切り上げ・四捨五入・切り捨てのいずれかを選択し、右のツマミで小数点以下の桁数を選択する。事務用電卓の中には、この機種のように計算結果を指定した桁数に丸めて表示できるものもある。

端数処理(はすうしょり)とは、与えられた数値を一定の丸め幅の整数倍の数値に置き換えることである。平たく、丸め(まるめ)ともいう。

常用的には、十進法で10の累乗(…100、10、1、0.1、0.01…)が丸め幅とされることが多いが、そうでない丸め幅をもつ処理は存在する。十進法以外のN進法について同様の概念を考えることもできる。
丸めの種類
凡例

丸めは任意の丸め幅に対し可能だが、以下では特に断らない限り、丸め幅を1とする(後段の「#例」では、丸め幅は0.1である)。任意の丸め幅で丸めるには、丸める前に丸め幅で割り、丸めた後に丸め幅をかける。

主に正数について述べるが、負数についても適宜述べる。
切り捨て・切り上げ

整数部分をそのまま残し、小数点以下を0とする丸めを「切り捨て」という。それに対し、小数点以下が0でなかった場合整数部分を1増やし、小数点以下を0とする丸めを「切り上げ」という。

負の数を考えると、「切り捨て」「切り上げ」に準ずる丸めは、4種類ある。それぞれ「○○への丸め」と呼ばれる。

符号を無視して絶対値を丸める場合、「切り捨て」は常に0へ近づく(または変わらない。以下では省略)ので「0への丸め (rounding toward zero; RZ)」、「切り上げ」は常に数直線上の無限遠点へ近づくので「無限大への丸め (rounding toward infinity; RI)」と呼ばれる。単に「切り捨て」「切り上げ」というと、これらをさす。

逆に、正数の場合と増減を同じ向きにする場合は、「切り捨て」は常に減るので「負の無限大への丸め (rounding toward minus infinity; RM)」、「切り上げ」は常に増えるので「正の無限大への丸め (rounding toward plus infinity; RP)」と呼ばれる。

「切り捨て」「切り上げ」は、最も計算が単純な丸めである。その一方で、丸め誤差上界が1(最大が1近い)と大きい。さらに悪いことに、誤差が常に同じ符号であるというバイアスがあり、丸めた数を多数足し合わせると、個数に比例して丸め誤差が累積する。この欠点のため、限られた目的にしか使われない。

数値が増えては困る/減っては困る場合は、「切り捨て」や「切り上げ」が使われる。

安全基準は、常に安全な方に丸められる。

誤差不確かさは、切り上げられる。

数値が実際より増えると誇張・虚偽・捏造・難解と見なされる恐れがあるときは、切り捨てられる。

数値が実際より減ると矮小化・虚偽・捏造と見なされる恐れがあるときは、切り上げられる。

(広義の)最近接丸め

丸め誤差を小さく抑えるには、常に最も近い整数(2つある場合はそのうちどちらか)に丸めればいい。これを「最近接丸め (round to the nearest)」という。ただし、単に「最近接丸め」というと、後述する「偶数への丸め」を意味することが多いので注意。

「最近接丸め」では、丸め誤差は最大で0.5で、「切り捨て」「切り上げ」の丸め誤差の半分になる。バイアスも、端数がランダム(すなわち、[0, 1)で一様分布)の場合は発生しない。端数がランダムでなく端数0.5が正の割合で発生する場合のみバイアスが発生するが、それでも、「切り上げ」「切り捨て」より格段に少ない(端数が全て0.5であるようなデータを四捨五入するといったワーストケースでは同じ程度になる)。

端数がちょうど半数だった場合どちらに丸めるかで、いくつかの変種がある。
四捨五入

十進法では、端数が0.5未満なら切り捨て、0.5以上なら切り上げる「半数切り上げ」の丸めを「四捨五入」という。JIS Z 8401で規則Bとして定められている[1]。「四捨五入」という呼び名は、小数第一位が4以下ならば切り捨て、5 以上ならば切り上げることに相当することから来ている。一般にはR丸めとも言う。

正数に対しては、0.5を足して切り捨てるという、単純なアルゴリズムで得られる。なお、負数に対して正常な結果を得ようとすれば、切り捨ては負の無限大への丸めである必要がある(0への丸めだと、たとえば?2が?1に丸められてしまう)。ただし、0.5を足して負への無限大へ丸めると、端数が0.5の場合に絶対値が減る(たとえば、?1.5は?1へと丸められる)。一方、JIS Z 8401では、負数は絶対値として丸める(?1.5は?2へと丸められる)。実際に、コンピュータで負の数に「0.5を足して切り捨て」た場合どうなるかは、負数と切り捨ての実装による[1]

端数が0.5のとき常に増える方向に丸められるため、(端数がランダムでない場合は)わずかに正のバイアスが発生しうる。
五捨五超入

端数が0.5以下なら切り捨て、0.5超なら切り上げる丸めを「五捨五超入」という。

0.5は常に切り上げられる四捨五入とは逆の特徴を持つ。端数がランダムでない場合は、わずかに負のバイアスが発生しうる。

正の数に対しては、0.5を引いて切り上げることで得られる。
偶数への丸め(round to even)

「偶数への丸め」(round to even)[2][3]は、端数が0.5より小さいなら「切り捨て」、端数が0.5より大きいならば「切り上げ」、端数がちょうど0.5なら「切り捨て」と「切り上げ」のうち結果が偶数となる方へ丸める(つまり偶数+0.5なら「切り捨て」、奇数+0.5ならば「切り上げ」となる)。JIS Z 8401で規則Aとして定められていて、規則B(四捨五入)より「望ましい」とされている[1]

端数0.5のデータが有限割合で存在する場合、「四捨五入」ではバイアスが発生するが、「偶数への丸め」ではバイアスが無い。つまり、多数足し合わせても、丸め誤差が特定の側に偏って累積することがない。ただし、偶数+0.5は現れるが奇数+0.5は現れないデータのように分布に特殊な特徴がある場合は、バイアスが発生することがある。

単に「偶数丸め」「最近接丸め」とも呼ばれる。JIS Z 8401で定められていることから「 JISの丸め方[4]」、あるいは同様にISO 31-0で定められていることから「ISO丸め」ともいう。英語では、誤差の累積を嫌い銀行家が好んで使ったため「銀行家の丸め (bankers' rounding)」、「銀行丸め」ともいう[注 1]。5が切り捨てられたり切り上げられたりするので「五捨五入」と呼ばれたり、端数がちょうど0.5の場合に整数部分が偶数なら「ゼロへの丸め」奇数なら「無限大への丸め」[注 2]になるので「偶捨奇入」と呼ばれたりもする。
奇数への丸め(round to odd)

「奇数への丸め」(round to odd)[2]は、偶数への丸めの対称である。端数が0.5より小さいなら「切り捨て」、端数が0.5より大きいならは「切り上げ」という点は最近接丸めとして同様だが、端数がちょうど0.5なら「切り捨て」と「切り上げ」のうち結果が奇数となる方へ丸める、という点が偶数への丸めの逆である。

端数0.5のデータが有限割合で存在する場合、「四捨五入」ではバイアスが発生するが、「奇数への丸め」ではバイアスが無い。つまり、多数足し合わせても、丸め誤差が特定の側に偏って累積することがない。ただし、偶数+0.5は現れるが奇数+0.5は現れないデータのように分布に特殊な特徴がある場合は、バイアスが発生することがある。
実用上は最近接丸めとなる丸め

定義は最近接丸めになっていないが、最近接丸めと等しくなる場合にのみ実用される丸めがいくつかある。
五捨六入

小数第一位が5以下ならば切り捨て、6以上ならば切り上げる丸めを「五捨六入」という。[注 3]

0.4を足して切り捨てることで得られる。0.55が0へ丸められることから、「五捨六入」が「最近接丸め」ではないことがわかる。端数がランダムなデータに対しは、やや強い負のバイアスがあるため、そのようなデータに対し「五捨六入」が使われることはまずない。

「五捨六入」が実用的なのは、端数が0.1の整数倍のみを取りうる場合に限られる。この場合の「五捨六入」は、0.1?0.5で切り捨て、0.6?0.9で切り上げ(0.5超0.6未満は発生しない)なので、「最近接丸め」の一種の「五捨五超入」と同じ結果となる。

例えば、麻雀のとあるローカルルールでは、最終的な得失点を五捨六入する。この場合の端数は常に0.1の整数倍(100の倍数を、1000の倍数に丸める)なので、丸め結果は「五捨五超入」と同じ結果となる。

コンピュータでは、プロセッサによっては「四捨五入」と「五捨六入」を均等に使い分け、バイアスを0にする工夫がなされているものがある。
四捨六入

アルシーアル麻雀得点計算では、かつて端数処理が行われる前の段階の計算による得点を丸めるときに「四捨六入」と呼ばれるものが採用されていた。これは丸める桁が必ず偶数になるためであり、実質的には「最近接丸め」である。また、#偶数への丸めが「四捨六入」と呼ばれる事例もある。
スウェディッシュ・ラウンディング

ニュージーランドでは現金での支払いの際、スウェディッシュ・ラウンディングと呼ばれる方法で端数処理が行われている。「スウェディッシュ・ラウンディング」とは、十進法で二捨三入や七捨八入と呼ばれる方法である。

5を単位とした端数が3未満なら切り捨て、3以上なら切り上げとなる。

端数がランダムな場合は、「五捨六入」と同様に非実用的である。しかし通常は、1刻みのデータに対し5を丸め幅として丸めるので、その結果は最近接値への丸めである。
IEEE丸め

IEEE 754で丸めモードとして定められている

最近接丸め(偶数)

0への丸め

正の無限大への丸め

負の無限大への丸め

の4つを「IEEE丸め」と総称する。
特殊な丸め
乱数丸め

ある数を丸める際に、[0,1)の一様乱数を発生させて、乱数の値が端数以上なら切り捨て、端数より小さければ切り上げる。

あるいはその数に一様乱数を足して切り捨てることで得られる。

丸め誤差は上界が1だが、分布が0近くに集まっているため、ランダムなデータに対する平均二乗誤差は切り捨て・切り上げよりは少ない。

任意の分布の端数に対して、バイアスがないのが特長である。たとえば、0?0.5の間にある端数が多かったとすると、偶数への丸めでは負のバイアスが生まれるが、乱数丸めではバイアスがない。

ディザの一種として使われる。
フォン・ノイマン丸め

常に奇数側へ丸める。

二進法では、切り捨てた後LSBをセットするという、簡単なアルゴリズムで得られる。

この方法の丸め誤差は切り捨て・切り上げと同程度で大きいが、ランダムなデータに対してはバイアスを持たない。
2回以上の丸めの禁止

同じ数値を2回以上丸めてはいけない。偶数への丸めの場合で、切り捨て過ぎてしまう例と、切り上げ過ぎてしまう例を説明する。

122.51 は 123 に丸められなければならない。しかし、まず 122.5 とすると、次は 122 になり、切り捨て過ぎになる。

123.49 も 123 に丸められなければならない。しかし、まず 123.5 とすると、次は 124 になり、切り上げ過ぎになる。

簡単な原則のように思えるかもしれないが、時に難しい問題を引き起こすことがある。たとえば、計算しているなんらかの値が、「偶数 + だいたい0.5」というような値になった時、それが「0.5ちょうどか、もしかしたら少し小さい」という場合は切り捨てできるが、それと対称的であるにもかかわらず「0.5ちょうどか、もしかしたら少し大きい」という場合は、「もしかしたら」の部分をはっきりさせなければ、正しい丸めができない。「奇数 + だいたい0.5」では逆になる[注 4]

与えられた数値を上で挙げた端数処理によって置き換えた場合の結果を示す。この例では、丸め幅は0.1である[注 5]

与えられた数値切り捨て切り上げ四捨五入五捨六入偶数への丸め
8.058.08.18.18.08.0
8.0518.08.18.18.08.1
8.158.18.28.28.18.2
8.258.28.38.38.28.2
8.2638.28.38.38.38.3
8.3478.38.48.38.38.3
8.358.38.48.48.38.4
8.458.48.58.58.48.4

太字の数値は、四捨五入の場合と異なる結果となるものである。
コンピュータでの丸め
低レベルの丸め

choppingは、あるビット以下を全て0にする。これは最も計算が簡単な丸めで、正の数に対しては切捨てとなる。負数に対する動作は負数の方式によるが、2の補数表現では負の無限大への丸めとなる。

choppingは、下位ビットを明示的に0にするほか、たとえば32ビットレジスタの上位16ビットを16ビットレジスタとして使うなどでも得られる。

choppingのあと、有効桁の中でのLSBをセットすると、フォン・ノイマン丸めとなる。
プログラミング言語の丸め関数

同様にビット操作で実装されるものであるが、プログラミング言語関数などで丸めの機能が提供されている。FPUで実装されていることも多い。

通常は、丸め関数の丸め幅は1で、それ以外の丸め幅に対しては、丸め前に丸め幅で割り丸め後に丸め幅を掛ける、というのが一般的なレシピである。これは、割ったり掛けたりするのはプログラマの責任であり、処理系は「小数点以下の丸め」のみに責任を持つ、という明確な責任の分界点のあらわれである。第2引数以降で丸め幅を指定できる環境もある(が、次で述べるように問題がある)。

Ruby(やPHP)など一部の言語のライブラリでは、(十進で)小数点以下何桁目で丸める、ということを引数で指定できるものがあるが、仕様に問題がある。よく知られているように一般的な二進の浮動小数点表現では、例えばきっかり 0.1 という値は表現できない。ということは、たとえば 0.11 を小数点以下1桁に丸めた結果として 0.1 が欲しい、と要求しても、その 0.1 は内部的には「丸めた」結果とは本来は言えないものだからである。そのような計算に関する、いくつかのモデルの立て方は考えられるが[5]、いずれにしろ元々の要求のほうが無理としたほうが妥当である。

丸め関数が返す値は、小数点以下が全てゼロの値、という意味では整数だが、は引数と同様に浮動小数点型というものも多い。これは理論的な理由よりは実際上の理由で、以前は一般的な整数型であった32ビット固定長整数で表現できる整数の範囲よりも、一般的な浮動小数点型である倍精度浮動小数点型で正確に表現できる整数の範囲のほうが広いためである。
floor, ceiling, truncatefloor関数(緑)とceil関数(赤)

多くの環境では、床関数(負の無限大へ)、天井関数(正の無限大へ)、切り落とし関数(0へ)が実装されている(床関数と天井関数)。それぞれの関数名には、次のようなものが使われる。

床関数 - floor

天井関数 - ceil、ceiling

切り落とし関数 - trunc、truncate、fix

これらは、5つのIEEE丸めモードのうちの3つの方向丸めに対応している。偶数への丸めの実装率は、これらより劣る。無限大への丸めが実装されている環境は少ない。

例: ±3.7 を丸め幅1で丸める。

ceil(3.7) = 4, ceil(-3.7) = -3

floor(3.7) = 3, floor(-3.7) = -4

trunc(3.7) = 3, trunc(-3.7) = -3

round

最近接丸めは、多くの環境にroundという関数がある。しかし、どの最近接丸めかを定めている一般的となっている標準(デファクトスタンダード)は存在しないので注意が必要である。たいていは四捨五入か偶数への丸めであるが[注 6]、明示的に選択できないことも多い。

プログラミング言語round(0.5)round(-0.5)
C99
C++11

Ruby1-1
.NET Framework
Python00
Java10
JavaScript1-0

C言語における型変換と端数処理演算子(int)

浮動小数点型から整数型へのキャストなどによる型変換では、処理が単純な切り捨てになるものが多く、負の場合は実装による。

C言語のmodf関数は、実数を整数部と小数部に分割する。整数部は0への丸めである。

(以下(§a.b)のようにして示すセクションは JIS X 3010-1993(C89)のもの)

C言語およびそれと同じ仕様の言語では、キャストなどによる浮動小数点型から整数型への型変換においては、その値は小数部が捨てられる(§6.2.1.3)。よって「0への丸め」が行われる。

C89では、数学ライブラリ(§7.5)に床関数floorと天井関数ceilがあり(§7.5.6)、浮動小数点型において正方向への丸めと負方向への丸めが計算できる。

C99では、四捨五入関数roundをはじめとして、fegetround/fesetround(これはmath.hではなくfenv.h)による丸めモードの取得と設定など、大幅な強化が図られている。

なお、浮動小数点演算の性質上、たとえば (int)(0.6/0.2) が 3.0 ではなく 2.0 になることがある。これは、浮動小数点表現では 0.6 や 0.2 を厳密に表現できないため、0.6/0.2 が 2.9999999999999996 のような値になるためである。
テーブルメーカーのジレンマ (数表作成者のジレンマ).mw-parser-output .ambox{border:1px solid #a2a9b1;border-left:10px solid #36c;background-color:#fbfbfb;box-sizing:border-box}.mw-parser-output .ambox+link+.ambox,.mw-parser-output .ambox+link+style+.ambox,.mw-parser-output .ambox+link+link+.ambox,.mw-parser-output .ambox+.mw-empty-elt+link+.ambox,.mw-parser-output .ambox+.mw-empty-elt+link+style+.ambox,.mw-parser-output .ambox+.mw-empty-elt+link+link+.ambox{margin-top:-1px}html body.mediawiki .mw-parser-output .ambox.mbox-small-left{margin:4px 1em 4px 0;overflow:hidden;width:238px;border-collapse:collapse;font-size:88%;line-height:1.25em}.mw-parser-output .ambox-speedy{border-left:10px solid #b32424;background-color:#fee7e6}.mw-parser-output .ambox-delete{border-left:10px solid #b32424}.mw-parser-output .ambox-content{border-left:10px solid #f28500}.mw-parser-output .ambox-style{border-left:10px solid #fc3}.mw-parser-output .ambox-move{border-left:10px solid #9932cc}.mw-parser-output .ambox-protection{border-left:10px solid #a2a9b1}.mw-parser-output .ambox .mbox-text{border:none;padding:0.25em 0.5em;width:100%;font-size:90%}.mw-parser-output .ambox .mbox-image{border:none;padding:2px 0 2px 0.5em;text-align:center}.mw-parser-output .ambox .mbox-imageright{border:none;padding:2px 0.5em 2px 0;text-align:center}.mw-parser-output .ambox .mbox-empty-cell{border:none;padding:0;width:1px}.mw-parser-output .ambox .mbox-image-div{width:52px}html.client-js body.skin-minerva .mw-parser-output .mbox-text-span{margin-left:23px!important}@media(min-width:720px){.mw-parser-output .ambox{margin:0 10%}}


次ページ
記事の検索
おまかせリスト
▼オプションを表示
ブックマーク登録
mixiチェック!
Twitterに投稿
オプション/リンク一覧
話題のニュース
列車運行情報
暇つぶしWikipedia

Size:40 KB
出典: フリー百科事典『ウィキペディア(Wikipedia)
担当:undef