2006年01月09日(月)

ゼロ除算についてあらためて考える

テーマ:プログラマの算数
小学生の頃だったろうか。「10 をゼロで割るとどうなるか?」という先生の質問に悩んだことがある。友達のひとりは「割り切れない」と答え、私はわけもわからずに関心した。

しかし、結局、正解は「ゼロで割り算をしてはいけない」というものだった。そんな問題出すんじゃないよ! これでは、「割り切れない」ではなく「やりきれない」ではないか。


普通の生活で、ゼロでの割り算をしなければならないような状況はないので、そんなことを気にする人は少ないかもしれない。しかし、プログラマにとって、ゼロ除算の回避は常識である。

プログラムがゼロ除算をすれば、その時点でエラーを出して異常終了してしまう。このため、プログラマが割り算を「書く」場合には、割る側の値(除数)がゼロにならないように、細心の注意を払う必要がある(※1)。簡単そうに思われるかもしれないが、除数が変数だったり関数の戻り値だったりすれば、なかなか大変なのである。


さて、そもそも「ゼロで割り算をしてはいけない」理由はなんだろうか。簡単な数字の計算なのに。

プログラミングの世界でよく目にする説明は、「ゼロ除算の結果の値は無限大(負の場合はマイナス無限大)になり、扱いきれなくなるため」というものだ。割り算では、除数が(正の数なら)小さくなるほど答えは大きくなるのだから、除数が0なら答えは「無限大」になるというわけだ。確かに、一般的にプログラムで扱う数値は有限(例えば、C言語の int なら INT_MIN~INT_MAX)なので、無限大は表現できない。

プログラマとしての理解はそんなところで十分かもしれない。私もその程度に考えていたが、今まで特に不都合はなかった。しかし、厳密には、これでは説明になっていないらしい。


調べているうちに、分かりやすい資料を見つけた。∫Integral Interval∫ さんの「0で割ってはいけない世界 」(PDF)である。

資料によれば、そもそも「無限大」は数ではない。数だとすると、「無限大+1」という計算ができるはずだが、その時点で、無限大より大きい数が出来てしまうことになり、おかしなことになる。「無限大」は数ではなく「状態」だというのだ(※2)。

また、割り算の除数を正の数からどんどん小さくしていけば、答えはどんどん大きくなるが、逆に負の数から大きくしていけば小さくなる。つまり、除数がゼロになった時点で、答えは「プラス無限大」であると同時に「マイナス無限大」でもある、というおかしなことになるのだ。

つまり、「無限大」という得体の知れない言葉では、説明したことにならないというわけだ。では、どう説明すべきか ・・・ ということについては、上記資料を参照いただきたい。結局のところ、ゼロ除算を認めるとゼロ以外の数が扱えなくなってしまうということらしい。

確かに、無理やりゼロ除算の答えを出そうとすると、矛盾が発生する。例えば、仮に「1÷0=a」とすると、「1=a×0」が成立するはずだが、ゼロは何に掛けても0なので、「1=0」となってしまうのである。


普段、何気なく順守してきた「ゼロ除算禁止のルール」だが、調べてみると奥が深かった。学生時代に文系であった私は、数学的知識は少ない方だ。今になってその面白さの一端に触れた気がする。



← このブログを誰かに読ませたいと思った方は、クリックを



※1
設計の時点で考慮されていればよいが、そこまでの細かさを期待できない場合が多い。

※2
例えば、データベースの「NULL」が数ではなく状態であるのと同じことだろう。



■関連記事
五捨五入
切捨て御注意



■リンク
ゼロ除算 【divide by zero】(e-Words)
ゼロ除算(IT用語辞典バイナリ)
数学の美しい世界へ∫Integral Interval∫ さん)
「a÷0」がいけない訳。しらぎくさいと。 さん)
なぜ0で割ってはいけないのか / 1÷0 / 何で0で割っちゃいけないんだ? (2ch)



異端の数ゼロ―数学・物理学が恐れるもっとも危険な概念
チャールズ サイフェ Charles Seife 林 大
早川書房 (2003/10)
おすすめ度の平均: 4.43
4 [アリストテレス&キリスト教]vs[ゼロ概念]の話が面白かった
5 とてもおもしろい!
4 不思議な数「0」の魅力に魔力


プログラマの数学
プログラマの数学
posted with amazlet on 06.01.09
結城 浩 結城 浩
ソフトバンククリエイティブ (2005/03/24)
売り上げランキング: 4,427
おすすめ度の平均: 4
4 文系の方向けの良書
4 文系プログラマにはよい
4 「情報工学をかじったことのないプログラマ」向けの本

AD
いいね!した人  |  コメント(2)  |  リブログ(0)
2005年12月24日(土)

五捨五入

テーマ:プログラマの算数
「四捨五入」といえば、読んで字のごとく、桁を丸め込むときに端数が4以下なら切り捨て、5以上なら切り上げることである。同様に、「五捨六入」は5以下を切り捨て、6以上を切り上げる。

では、「五捨五入」とは何だろうか(※1)。これは、端数が4以下なら切り捨て、6以上なら切り上げ、5なら結果が偶数になるように切り捨てたり切り上げたりするというものだ。例えば、3.5 を五捨五入して整数に丸めると 4 になるが、2.5 だと 2 になる。つまり、「最も近い偶数に丸める」という計算方法なのである。

この方法は、ISO 31-0:1992 や JIS Z 8401:1999、IEEE 754 で数値を丸める標準的な方法として規定されている(※2)。例えば、VB の丸め込み関数 Round() などは、そのような動きをする。

我々は普段、四捨五入には慣れ親しんでいるが、五捨五入についてはそうでもない。しかし、五捨五入の方が誤差が少ないため、システムの要件としては、好まれることもあるようだ(※3)。


こうした微妙な計算方法の違いが、不幸なバグを生むことは多い。

例えば、四捨五入をするつもりで、「標準」の丸め込み関数を使って、痛い目にあったという話はよく耳にする。

あるいは、仕様書などに「四捨五入せよ」と書いてあったが、実際には五捨五入すべきだった、といったケースもある。

学校で学んできたような一般的なやり方が、どの業界でも一般的(標準的)だとは限らない。そのことを端的に示したよい例かもしれない。




← このブログを誰かに読ませたいと思った方は、クリックを



※1
「銀行型の丸め」と言った方が通りがいいだろうか。他にも、「偶捨奇入」、「偶数への丸め」、「JIS丸め」など、いろいろな呼び方がある。なお、JIS規格に従えば、単に「丸め」と言ったら、五捨五入のことを指すようだ。

※2
こちらのページ によると、JIS規格では、五捨五入が「規則A」、四捨五入が「規則B」として規定されていて、特に明記されていなければ、規則Aを使うこととされているようである。また、「切捨て御注意 」に書いたような、負の数の問題については、「絶対値にしてから適用する」とされているようだ。JIS Z 8401:1999 の原文は、JSA Web Store から PDF を購入することが出来る。

※3
5 は 0 と 10 の中間に位置するのだから、切り上げと切り捨てを平等に行うほうが誤差が少ない。例えば、3.5 + 2.5 は 6.0 だが、四捨五入後に加算すると、4 + 3 = 7 と1大きくなる。五捨六入だと、3 + 2 = 5 で逆に1小さくなる。五捨五入なら 4 + 2 で、ぴったり 6 だ。誤差の問題だけでいえば、奇数に丸めてもいいのだが、0 を基点に考えたほうが分かりやすいから、偶数に丸めるのだろう。



■関連記事
切捨て御注意
ゼロ除算についてあらためて考える
曖昧言葉



■リンク
端数処理(ウィキペディア)
油断ならない四捨五入(「株式会社データアクション」さん)
[.NET] 四捨五入 (「biac の それさえもおそらくは幸せな日々」さん)



Excelで遊ぶ手作り数学シミュレーション
田沼 晴彦
講談社 (2004/01/21)
売り上げランキング: 41,420
おすすめ度の平均: 5
5 エクセルのもう一つの使い方!
5 文系にこそ
5 パソコンに眠っているEXCELを使いこなそう


プログラミングのための線形代数
平岡 和幸 堀 玄
オーム社 (2004/10)
売り上げランキング: 3,237
おすすめ度の平均: 5
5 最高
5 ビジュアル系
5 線形代数の概念を徹底的に解説した本


AD
いいね!した人  |  コメント(5)  |  リブログ(0)
2005年05月14日(土)

切捨て御注意

テーマ:プログラマの算数
プログラミングをしていて、簡単な数値の計算が予想外の結果になってしまって、驚いたことはないだろうか?


5 を 2 で割ったらいくつになるか?

もちろん、2.5 であるが、これは実数での計算だ。C言語で int と表現されるような「整数型」の計算では、小数点以下は扱えない。そこで、少数点以下は切り捨てて計算される。例えば、5 ÷ 2 なら、2 になるのである(※1)。

ここまではよいだろう。では、-5 ÷ 2 ではどうなるか?

-2.5 の小数点以下が切り捨てられて -2 になる? しかし、切り捨てたら値は小さくなるはずなので、-3 になる、という考え方もある。


整数の割り算は、いわゆる「商と余り」を求めることでもある。身近な(?)2つの電卓プログラムで、-5 を 2 で割った「余り」を計算させ、切捨て方法の違いを体験してみた。

まず、Windows XP 付属の電卓で "-5" → [Mod] → "2" とやってみた。-1 が返ってきた。

  -5 ÷ 2 = -2 … -1 (商 = -2、余り = -1)

ということである。

次に、「Google 電卓機能」で、「-5 % 2」を求める と、答えは 1 だという。

  -5 ÷ 2 = -3 … 1 (商 = -3、余り = 1)

ということだろう。


プログラマとして認識しておきたいのは、このような基本的な計算ですら、処理系(プログラミング言語など)によって動作が違うことがある、ということである(※2)

初めて使う言語は、コードの書き方の違い、ライブラリの違いなどは大いに気にすると思う。しかし、こうした、演算仕様の違いなどには、意外と気が及ばないものだ。

ちょっとしたプログラムを書いて動かしてみれば確認できることなので、今使っている言語ではどうなのか、調べてみるといいだろう。




※1
詳しく調べていないが、切り捨てないで、例えば四捨五入のような「丸め込み」をする言語(処理系)もあるかもしれない。

また、型に厳密でない言語では、整数同士で割り算をしても、「答えの型」が勝手に実数になってしまうことも多い。このような場合、例えば、(5 / 2) * 2 + (5 % 2) が 5 にならない というように、意図しないことが起こる場合があるので注意。

※2
ちょっと手元で試しただけでも、Java では -5 / 2 は -2 だが、Ruby では -3 だった。-5 % 2 については、Java は -1、Ruby は 1 を返した。同じ処理系内では、商と余りの関係に一貫性があるようだ。ただし、Ruby では、(-5/2) が -3 である一方、(-2.5).to_int が -2 となった。



■関連記事
五捨五入
ゼロ除算についてあらためて考える



Excelで学ぶやさしい数学―三角関数から微積分まで
高橋 幸久 渡辺 八一
オーム社 (2004/01)
売り上げランキング: 141,472


プログラマの数学
プログラマの数学
posted with amazlet on 06.04.03
結城 浩 結城 浩
ソフトバンククリエイティブ (2005/03/24)
売り上げランキング: 4,427
おすすめ度の平均: 4
4 文系の方向けの良書
4 文系プログラマにはよい
4 「情報工学をかじったことのないプログラマ」向けの本


AD
いいね!した人  |  コメント(1)  |  リブログ(0)

AD

ブログをはじめる

たくさんの芸能人・有名人が
書いているAmebaブログを
無料で簡単にはじめることができます。

公式トップブロガーへ応募

多くの方にご紹介したいブログを
執筆する方を「公式トップブロガー」
として認定しております。

芸能人・有名人ブログを開設

Amebaブログでは、芸能人・有名人ブログを
ご希望される著名人の方/事務所様を
随時募集しております。