読者です 読者をやめる 読者になる 読者になる

小清水さんとコンピューター数学

コンピューター・数学 に関することを書きます

浮動小数点の丸めの方向と性質 (1)

小清水です。

前回の記事では 浮動小数点数による計算のため に、

計算が はちゃめちゃ・わやくちゃ になる例を紹介しました。

math-koshimizu.hatenablog.jp


Abstract

今回は そんな浮動小数点数

もう少し踏み込んだ話をするための準備記事になります。

実数を浮動小数点に近似する 丸め について詳しく踏み込んでみます。

4つの代表的な丸めを定義して考察を加えていきます。

四捨五入のような考え方がイケてない理由なども登場します。

浮動小数点数のざっくりした理解

2進p桁の浮動小数点数とは 次のように表現できる数:

 (-1)^s \times \left( 1 + \frac{ m_1 }{ 2^1} + \frac{ m_2 }{ 2^2} \dots + \frac{ m_{p-1}}{2^{p-1}} \right) \times 2^e \\
= (-1)^s \times (1.m_1 m_2 \dots m_{p-1})_2 \times 2^e \\
= (符号部) \times (仮数部) \times 2^{(指数部)}

になります。ただし、

 s, m_i \in \{0, 1\}, e \in \mathrm{Z}

例えば、2進3桁の浮動小数点の分布は次のようになります。

f:id:curekoshimizu:20161204201749p:plain

注意.

ここでざっくりと書いたのは、

ここでは e の区間を整数全体としているものの、

本来は特定の数の間で限定されていたり、

非正規化数の話が抜けているためです。

いつか正確な内容をブログにアップする予定です。

実数は基本的に浮動小数点数で表せない

上図で表した通り  \pi浮動小数点数で表せません。

そのため、浮動小数点数へと近似してあげる必要があります。

この、実数から浮動小数点への近似函数丸め といいます。

代表的な丸め函数

代表的な丸め方法としてこの4つがあります:

  • RN(x) : x の 最近接偶数方向丸め (round to nearest even)
  • RU(x) : x の 正の無限大方向丸め (round up)
  • RD(x) : x の 負の無限大方向丸め (round down)
  • RZ(x) : x の 0方向丸め (round toword zero)

f:id:curekoshimizu:20161204200848p:plain

先程の例の場合、

 \pi は RN・RD・RZ の場合に

 (1.00)_2 \times 2^1 = 3

へと丸められます。これは、

RN は最も近い浮動小数点数に丸められる から、

RD はその数以下の浮動小数点のうちで最も近い浮動小数点数に丸められる から、

RZ はその数が正であれば RD と同じ丸め方向に・負であれば RU と同じ方向に丸められる からです。

また、RU の場合には

 (1.01)_2 \times 2^1 = 3.5

へと丸められます。これは RU がその数以上の浮動小数点のうちで最も近い浮動小数点に丸められる からです。

RN の 最近接偶数方向丸めとは?

上の説明では RN の 最近接 たる所以、

つまり、最も近い浮動小数点に丸められるというところを説明しました。

問題は 偶数方向 の意味になります。

こちらは次のような 浮動小数点数のちょうど真ん中の数 に対する規則になります。

f:id:curekoshimizu:20161204213832p:plain

この図の説明通り、

最近接の2数の浮動小数点のうち、仮数部の最下位が 偶数(0) の方を選択する

という意味になります。

そのため、先の 3.25 だけでなく 2.75 についても 3 側に丸められるということになります。

f:id:curekoshimizu:20161204213843p:plain

偶数側ばかり選んで不平等に感じる?それは次を御覧ください。

RN は なぜ四捨五入のような規則ではない?

我々は 四捨五入 という規則を知っており、

それに近い規則を考えれば 零捨一入 という考えが普通に感じます。

このようにすれば 偶数値ばかり選択されず不平等さは生じません。

しかしながら、

そもそも 四捨五入 はある困った性質があり、

浮動小数点の丸めでは 四捨五入・零捨一入 というのは採用されませんでした。

最後に 2進法の場合 を示すとして、

ここでは我々にとって 身近な四捨五入直感に反してしまう例 を紹介して、

日常生活でも使えるウンチクにしたいと思います。

四捨五入を採用すると直感に反してしまう例

実数空間では

 a \quad + b - b \quad + b - b \quad + b - b\quad = a

というのは常識だと思います。

今回の例は、この等式が怪しくなるという話です。

10進3桁で考えることとして、

 a = (1.00)_{10} \times 10^0 = 1, b = (5.55)_{10} \times 10^{-1} = 0.555

a に b を足して引くということを繰り返すとどんどん大きくなるという例を示します。

四捨五入の丸め方法を R(x) と書くことにしますと

 
\mathrm{R}( \mathrm{R}(1.00 + 5.55\times 10^{-1}) - 5.55\times 10^{-1}) \\
= \mathrm{R}( \mathrm{R}(1.555) - 5.55\times 10^{-1}) \\
= \mathrm{R}( 1.56 \times 10^0 - 5.55\times 10^{-1}) \\
= \mathrm{R}( 1.005 \times 10^0 ) \\
= \mathrm{R}( 1.01 \times 10^0 )

a+b-b をやって 1.00 が 1.01 に大きくなりました。

さらに繰り返しましょう。

 
\mathrm{R}( \mathrm{R}(1.01 + 5.55\times 10^{-1}) - 5.55\times 10^{-1}) \\
= \mathrm{R}( \mathrm{R}(1.565) - 5.55\times 10^{-1}) \\
= \mathrm{R}( 1.57 \times 10^0 - 5.55\times 10^{-1}) \\
= \mathrm{R}( 1.015 \times 10^0 ) \\
= \mathrm{R}( 1.02 \times 10^0 )

先の結果に +b-b をすると 1.00 が 1.02 まで大きくなることが分かりました。

さらに繰り返しましょう。

 
\mathrm{R}( \mathrm{R}(1.02 + 5.55\times 10^{-1}) - 5.55\times 10^{-1}) \\
= \mathrm{R}( \mathrm{R}(1.575) - 5.55\times 10^{-1}) \\
= \mathrm{R}( 1.58 \times 10^0 - 5.55\times 10^{-1}) \\
= \mathrm{R}( 1.025 \times 10^0 ) \\
= \mathrm{R}( 1.03 \times 10^0 )

先の結果に +b-b をすると1.03 になりました。

実はまだまだずーっと続くのですが、このあたりで止めましょう。

これを drifting といいます。

注意. 2進法3桁で同じような例をつくるには

 a = (1.11)_2 \times 2^0 , b = (1.11)_2 \times 2^{-1}

で同じことをすればいいです。

Theorem 1. (RN は 連続した加減算で drifting が発生しない)

RN : 最近接偶数方向丸めに対して

 \mathrm{RN}(\mathrm{RN}(\mathrm{RN}(\mathrm{RN}(a+b) -b)+b)-b) = \mathrm{RN}(\mathrm{RN}(a+b)-b)

ということが知られています。

四捨五入・零捨一入という規則ではなく、

偶数方向丸めというものが採用されているのはこの性質のためです。

小清水は現時点でこの証明方法を知りません。

証明を知っている方は是非教えてください。

丸め誤差と誤差の関係をまとめる

再び浮動小数点の分布図を見ながら考えてみると、

f:id:curekoshimizu:20161204221456p:plain

RU・RD・RZ による丸め誤差隣合う浮動小数点の間隔 未満となります。

 \mathrm{RU}(\pi) はほぼ対岸側の浮動小数点に丸められていることを考えれば、

限りなくもう一方の浮動小数点数に近い実数を考えればこの事実がわかるかと思います。

一方、RN による丸め誤差は 隣り合う浮動小数点のうち 近い方 であるから、(隣り合う浮動小数点数の間隔)/2 が最大となります。

これらをまとめると

Proposition 1 (丸めと絶対誤差の関係)

2進p桁の浮動小数点への実数の丸めは

 2^n \leq |x| < 2^{n+1} \; (n \in \mathrm{Z}) ならば
 \displaystyle \left| x - \mathrm{RN}(x) \right| \leq 2^{n-p} \left(= \frac{1}{2^{p-1}}\cdot 2^n \cdot \frac{1}{2} \right) 
 \displaystyle \left| x - \mathrm{RU}(x) \right| < 2^{n-p+1} \left(= \frac{1}{2^{p-1}}\cdot 2^n  \right) 
 \displaystyle \left| x - \mathrm{RD}(x) \right| < 2^{n-p+1} \left(= \frac{1}{2^{p-1}}\cdot 2^n  \right) 
 \displaystyle \left| x - \mathrm{RZ}(x) \right| < 2^{n-p+1} \left(= \frac{1}{2^{p-1}}\cdot 2^n  \right) 

最後に

ここまで代表的な丸めについて説明し

その誤差について説明しました。

ここまで説明できましたので

  • 相対誤差 について
  • RN・RU・RD・RZ の使い道

などを記載予定だったのですが、

長くなりすぎたので

次回のブログ記事にまわしたいと思います。