From: GOTO Kentaro Date: 2007-01-15T12:56:16+09:00 Subject: [ruby-list:43125] Re: 浮動小数点を比較するには 一般には対象ごとに基準を考えるべきで機械的に判断できる場合は限られます。 たとえば、0b を二進数の接頭辞とすると1.1と0.9の内部表現はそれぞれ 1.1 は 0b1.0001100110011001100110011001100110011001100110011010 * 2**0 0.9 は 0b1.1100110011001100110011001100110011001100110011001101 * 2**-1 です。見て分かるようにどちらも本来は循環小数です。打ち切られる位置は 2進で見たときに最初の1が整数部にくるようにシフトして、残り52桁目と なっています。 演算の結果は上記の内部表現が元になっています。 1.1-1.0 と 1.0-0.9 の結果と比較のために 0.1 をそれぞれ書くとこんな感じで違います。 1.1-1.0 = 0b1.1001100110011001100110011001100110011001100110100000 * 2**-4 1.0-0.9 = 0b1.1001100110011001100110011001100110011001100110011000 * 2**-4 0.1 = 0b1.1001100110011001100110011001100110011001100110011010 * 2**-4 1.1-1.0 のほうが 1.0-0.9 より有効桁数が小さく見えますが、 これがいわゆる桁落ちです。互いに近い数の減算を行ったために 有効数字が減る現象です。 ちなみに大きさがすごく異なる数を加算したときに小さいほうが結果に 反映されないのは情報落ちというようです。 現実の場面では単純な四則演算1回で終わるわけではないので、 実用上は、こういった有効桁数の基本的な扱いをもとに自分で 許容できる誤差を定める必要がある点は手計算と同じです。 測量計算というのがどういうものか知りませんが、仮に長さの計測が 有効数字4桁だったら、内部では52ビットあっても全部を気にする必要は ないわけで、演算結果も有効数字4桁で解釈すればよいのではないでしょうか。 比較を使った単体テストが書きにくいことには同意しますが、 あきらめるしかないと思います。グラフとかを目視して確認する以上の 万能の方法は知りません。 なお機械イプシロンは、 0b1.0000000000000000000000000000000000000000000000000000 * 2**-52 のことです。この数は1.0より大きなFloatのうちで最小のもの 0b1.0000000000000000000000000000000000000000000000000001 * 2**0 と、1.0 の差の大きさです。 0.5 より大きなFloatのうちで最小のものと、0.5 の差の大きさは、この半分になります。 1.0より小さなFloatのうちで最大のものと、1.0 の差の大きさもそうです。 こういうのって理論的な解析には使いやすいですが実用上はどうかなあと思います。 ごとけん