端数処理のソースを表示
←
端数処理
移動先:
案内
、
検索
あなたには「このページの編集」を行う権限がありません。理由は以下の通りです:
要求した操作を行うことは許可されていません。
このページのソースの閲覧やコピーができます。
'''端数処理'''(はすうしょり)または'''丸め'''(まるめ)とは、与えられた数値を、ある一定の丸め幅の[[整数]]倍の数値に置き換えることである。常用的には、[[10]]の[[累乗]](…、100、10、1、0.1、0.01、…)が丸め幅とされることが多い。 == 丸めの種類 == === 凡例 === 丸めは任意の丸め幅に対し可能だが、以下では特にことわらない限り、丸め幅を1とする。任意の丸め幅で丸めるには、丸める前に丸め幅で割り、丸めた後に丸め幅をかければいい。 [[記数法]]が問題になるときには、[[10進法]]で表されているものとする。 主に正の数について述べるが、適宜、負の数についても述べる。 === 切り捨て・切り上げ === 整数部分をそのまま残し、小数点以下を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未満なら切り捨て、0.5以上なら切り上げる丸めを「四捨五入」という。[[日本工業規格|JIS]] Z 8401で規則Bとして定められている。「四捨五入」という呼び名は、小数第1位が4以下ならば切り捨て、5 以上ならば切り上げることに相当することから来ている。この呼称は10進法での表現に依存しているので、10進法に限定しないときは'''R丸め'''という。 正の数に対しては、0.5を足して切り捨てるという、単純なアルゴリズムで得られる。なお、負の数に対して正常な結果を得ようとすれば、切り捨ては負の無限大への丸めである必要がある(0への丸めだと、たとえば−2が−1に丸められてしまう)。ただし、0.5を足して負への無限大へ丸めると、端数が0.5の場合に絶対値が減る(たとえば、−1.5は−1へと丸められる)。一方、JIS Z 8401では、負の数は絶対値として丸める(−1.5は−2へと丸められる)。実際に、[[コンピュータ]]で負の数に「0.5を足して切り捨て」た場合どうなるかは、負の数と切り捨ての実装による。 端数が0.5のとき常に増える方向に丸められるため、(端数がランダムでない場合は)わずかに正のバイアスが発生しうる。 ==== 五捨五超入 ==== 端数が0.5以下なら切り捨て、0.5超なら切り上げる丸めを「五捨五超入」という。 0.5は常に切り上げられるという、四捨五入とは逆の特徴を持つ。端数がランダムでない場合は、わずかに負のバイアスが発生しうる。 正の数に対しては、0.5を引いて切り上げることで得られる。 ==== 最近接偶数への丸め ==== 最近接偶数への丸め (round to the nearest even; RN) は、端数が0.5より小さいなら切り捨て、端数が0.5より大きいならは切り上げ、端数がちょうど0.5なら切り捨てと切り上げのうち結果が[[偶数]]となる方へ丸める。JIS Z 8401で規則Aとして定められていて、規則B(四捨五入)より「望ましい」とされている。 四捨五入ではバイアスが発生する、端数0.5のデータが有限割合で存在する場合でも、バイアスがないのが特徴であり、多数足し合わせても丸め誤差が特定の側に偏って累積することがない(偶数+0.5は現れるが奇数+0.5は現れない、といったような特徴があるデータであれば、やはりバイアスはあらわれる)。 単に「'''偶数丸め'''」「'''最近接丸め'''」とも呼ばれる。JISで定められていることから「'''JIS丸め'''」、あるいは同様に[[ISO-31]]で定められていることから「'''ISO丸め'''」ともいう。英語では、誤差の累積を嫌い[[銀行家]]が好んで使ったため「銀行家の丸め (bankers’ rounding)」ともいう。5が切り捨てられたり切り上げられたりするので「五捨五入」と呼ばれたり、偶数の上が切り捨てられ奇数の上が切り上げられるので「偶捨奇入」と呼ばれたりもする。 === IEEE丸め === [[IEEE 754]]で丸めモードとして定められている * 最近接偶数への丸め * 0への丸め * 正の無限大への丸め * 負の無限大への丸め の4つを「IEEE丸め」と総称する。 === 実用上は最近接丸めとなる丸め === 定義は最近接丸めになっていないが、最近接丸めと等しくなる場合にのみ実用される丸めがいくつかある。 ==== 五捨六入 ==== 小数第1位が5以下ならば切り捨て、6以上ならば切り上げる丸めを「五捨六入」という。 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で五捨六入することに等しい。つまり、(5を単位とした)端数が3未満なら切り捨て、3以上なら切り上げとなる。 端数がランダムな場合は、五捨六入と同様に非実用的である。しかし通常は、1刻みのデータに対し5を丸め幅として丸めるので、その結果は最近接値への丸めである。 === 特殊な丸め === ==== 乱数丸め ==== [0,1)の一様[[乱数]]を発生させ、端数以上なら切り捨て、端数より小さければ切り上げる。 一様乱数を足して切り捨てることで得られる。 丸め誤差は上界が1だが、分布が0近くに集まっているため、ランダムなデータに対する平均二乗誤差は切り捨て・切り上げよりは少ない。 任意の分布の端数に対して、バイアスがないのが特長である。たとえば、0~0.5の間に端数が多かったとすると、最近接偶数への丸めでは負のバイアスが生まれるが、乱数丸めではバイアスがない。 [[ディザ]]の一種として使われる。 ==== フォン・ノイマン丸め ==== 常に奇数側へ丸める。 [[2進法]]では、切り捨てた後[[最下位ビット|LSB]]をセットするという、簡単なアルゴリズムで得られる。 丸め誤差は切り捨て・切り上げと同程度で大きいが、ランダムなデータに対してはバイアスがないという性質は持っている。 == 2回以上の丸めの禁止 == 同じ数値を2回以上丸めてはいけない。たとえば、122.51を最近接偶数へ丸めるときに、まず122.5とし、次に122とすると、結果が違ってしまう。 == 例 == 以下の数値を上であげたような端数処理により有効数字 2 桁にする場合を考える。 {|class="wikitable" style="text-align:center" |- !もとの数値||切り捨て||切り上げ||四捨五入||五捨六入||偶数丸め |- |8.05||8.0||8.1||8.1||8.0||'''8.0''' |- |8.15||8.1||8.2||8.2||8.1||8.2 |- |8.25||8.2||8.3||8.3||8.2||'''8.2''' |- |8.26||8.2||8.3||8.3||8.3||8.3 |- |8.34||8.3||8.4||8.3||8.3||8.3 |- |8.35||8.3||8.4||8.4||8.3||8.4 |- |8.45||8.4||8.5||8.5||8.4||'''8.4''' |} == コンピュータでの丸め == === 低レベルの丸め === '''chopping'''は、あるビット以下を全て0にする。これは最も計算が簡単な丸めで、正の数に対しては切捨てとなる。負数に対する動作は負数の方式によるが、[[2の補数]]表現では負の無限大への丸めとなる。 choppingは、下位ビットを明示的に0にするほか、たとえば32ビットレジスタの上位16ビットを16ビットレジスタとして使うなどでも得られる。 choppingのあと、有効桁の中でのLSBをセットすると、フォン・ノイマン丸めとなる。 === 丸め関数 === 同様にビット操作で実装されるものであるが、[[プログラミング言語]]の[[サブルーチン|関数]]などで丸めの機能が提供されている。[[FPU]]で実装されていることも多い。 通常は、丸め関数の丸め幅は1で、それ以外の丸め幅に対しては、丸め前に丸め幅で割り丸め後に丸め幅を掛ける、というのが一般的なレシピである。第2引数以降で丸め幅を指定できる環境もある。 丸め関数が返す値は、小数点以下が全てゼロの値、という意味では整数だが、[[データ型|型]]は引数と同様に[[浮動小数点数|浮動小数点型]]というものも多い。これは、浮動小数点型としては一般的な倍精度浮動小数点型の仮数部が50ビット前後あるのに対し、固定長の整数型は昔は大きいものでも32ビットだったため、入りきらない値の可能性もあり不便だったためである。64ビットの整数型も昨今は標準化されるなどしているが、互換性の問題もあり過去の仕様が継承されている。 ==== floor ceil trunc ==== [[File:Ceilfloor nt.png|thumb|300px|floor関数(緑)とceil関数(赤)]] 多くの環境では、床関数(負の無限大へ)、天井関数(正の無限大へ)、切り落とし関数(0へ)が実装されている([[床関数と天井関数]])。それぞれの関数名には、次のようなものが使われる。 * 床関数 - '''floor''' * 天井関数 - '''ceil'''、'''ceiling''' * 切り落とし関数 - '''trunc'''、'''truncate'''、'''fix''' これらは、4つのIEEE丸めモードのうち3つに対応している。4つ目の最近接偶数への丸めの実装率は、これらより劣る。IEEE丸めに含まれない無限大への丸めが実装されている環境は少ない。 例: ±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 [[Microsoft Excel]] の <code>ceiling</code> 関数は、その名に反して、無限大への丸め(正負によらず絶対値が大きい方への丸め)をおこなう。例えば、<code>ceiling(-4.5,1)</code> であれば −5 となる。 ==== その他の丸め関数 ==== 浮動小数点型から整数型へのキャストなどによる[[型変換]]では、処理が単純な切り捨てになるものが多く、負の場合は実装による。 [[C言語]]の'''modf'''関数は、実数を整数部と小数部に分割する。整数部は0への丸めである。 多くの環境に'''round'''という関数があるが、環境によって動作が異なるので、使用には注意が必要である。一般的には、四捨五入か最近接偶数への丸めをすることが多い。 == C言語における型変換と端数処理 == [[Image:Int function.svg|thumb|right|演算子<code>(int)</code>]] (以下(§a.b)のようにして示すセクションは JIS X 3010-1993([[C89]])のもの) [[C言語]]およびそれと同じ仕様の言語では、キャストなどによる浮動小数点型から整数型への[[型変換]]においては、その値は小数部が捨てられる(§6.2.1.3)。よって「0への丸め」が行われる。 [[C89]]では、数学ライブラリ(§7.5)に床関数floorと天井関数ceilがあり(§7.5.6)、浮動小数点型において正方向への丸めと負方向への丸めが計算できる。 [[C99]]では、四捨五入関数<code>round</code>をはじめとして、<code>fegetround</code>/<code>fesetround</code>(これはmath.hではなくfenv.h)による丸めモードの取得と設定など、大幅な強化が図られている。 なお、浮動小数点演算の性質上、たとえば (int)(0.6/0.2) は 3.0 ではなく 2.0 になる(なってもおかしくない)ので注意が必要である。これは浮動小数点表現では 0.6 や 0.2 を厳密に表現できないため、0.6/0.2 が、厳密には 2.9999999999999996 のような値になるためである。<!-- とりあえず以下は書く所が違うような気が --><!--これらの演算により値の有意性が失われるので、それにより[[丸め誤差]]が大きくなるおそれがある。例えば、正しくは 0.6/0.2 = 3 であるにもかかわらず、C言語の多くの実装において <code>(int)(0.6/0.2)</code> は 2 となってしまう。これは、[[コンピュータ]]は内部処理に[[二進法]]を用いており、その二進法では0.6や0.2を[[有限小数]]で表すことができないため、0.6/0.2 が 2.999999999999999555910790149937 と計算されることに起因する。 浮動小数点型が実価を保存するのに使用される状況においては、[[POSIX]] の floor() 関数と同様、[[Java]] ([[Java Development Kit|Sun JDK]] version 1.5.0_05), [[Perl]] (version 5.8.0), [[PHP: Hypertext Preprocessor|PHP]] (version 5.2.1) といった他の多くの言語についても同様の誤差が現れる。 このような現象が問題になる場合、内部処理に[[二進化十進表現|十進法]]を用いることがある。しかし、この方法で解決されるのは問題の一部に過ぎず、<code>(int)((4.0/9.0) * 9.0)</code> が 3 となってしまう(本来は 4 となるべき)ような問題は十進法を用いても解決されない(この結果は (4.0/9.0) * 9.0 = 0.44444...4444 * 9.0 = 3.99999...9996 という計算によるものであり、二進法でも十進法でも表し得る最も近い数で近似したところで問題は変わらない)。 解決策としては、微小な定数 <code>e</code>(例えば <code>e = 0.00000001</code> など)を定めた上で、正の <code>x</code> に対して床関数を <code>floor(x) = (int)(x + e)</code>、天井関数を <code>ceiling(x) = (int)(x + e) + 1</code> などと定義する方法がある。 より綺麗な解決法としては、有理数を正確に表せるような[[データ型]]を用いる、つまり[[除法|除算]]などが行われる時にそこで丸め誤差が発生するのを避けるという方法がある。例えば、浮動小数点型の被除数と正の整数型の除数との組を保持しておくという方法である。この方法では途中計算やその間のデータ保持はすべてこの型で行われ、最後に結果を表示するときにのみ十進の浮動小数点型の表示が計算される。これにより正しい丸めが行われる。尚、この方法は [[Microsoft Windows|Windows]] 付属の[[電卓 (Windows)|電卓]] で用いられている。 --> == 関連項目 == * [[統計学]] * [[浮動小数点数]]、[[固定小数点]] (コンピュータの数値) * [[正確度と精度]] {{デフォルトソート:はすうしより}} [[Category:測定]] [[Category:数の表現]] [[Category:コンピュータの算術]] [[Category:JIS|Z 8401]] [[Category:数学に関する記事]]
端数処理
に戻る。
案内メニュー
個人用ツール
ログイン
名前空間
ページ
議論
変種
表示
閲覧
ソースを表示
履歴表示
その他
検索
案内
メインページ
コミュニティ・ポータル
最近の出来事
新しいページ
最近の更新
おまかせ表示
sandbox
commonsupload
ヘルプ
ヘルプ
井戸端
notice
bugreportspage
sitesupport
ウィキペディアに関するお問い合わせ
ツール
リンク元
関連ページの更新状況
特別ページ
ページ情報