[#43103] 浮動小数点を比較するには — wada toshiki <wada-ts@...>

お世話になります。

21 messages 2007/01/11
[#43105] Re: 浮動小数点を比較するには — NISHIMATSU Takeshi <t_nissie@...> 2007/01/11

> Rubyレシピブック(P290)で 比較する数値の差を Float::EPSILON と比較する方法があり

[ruby-list:43115] Re: 浮動小数点を比較するには

From: wada toshiki <wada-ts@...>
Date: 2007-01-13 06:11:38 UTC
List: ruby-list #43115
KURODA Hirakuさん wrote:
> 初めまして、黒田と申します。
> ====
> 0.1 = 1.00000000000000005551e-01
> x   = 1.00000000000000005551e-01
> x   = 2.00000000000000011102e-01
> (中略)
> x   = 1.90000000000000057732e+00
> x   = 2.00000000000000044409e+00
> 2.0 = 2.00000000000000000000e+00
> 4.44089209850063e-16
> 8.88178419700125e-16
> 2.22044604925031e-16
> false
> ====

p 2.0.near_to(x)
p x.near_to(2.0)

の動きの違いは、(self - b).abs / abs 2.0を分母にするか、xを分母にするかだったわ
けですね。しかし、3.0になるとどちらも False になります。

> 実数の0.1とFloatの0.1(実際は0.100...0551)の差が予想よりも大きくて、20回
> 積み重ねてEPSILONを飛び出したといった感じでしょうか?
> Rubyは
>  ruby 1.8.2 (2005-04-11) [i386-linux]
> です。

0.1+0.1としても単純に累積はしないのですが。

0.1  = 1.00000000000000010000e-01
0.2  = 2.00000000000000010000e-01
0.3  = 3.00000000000000040000e-01
0.4  = 4.00000000000000020000e-01

> ところで
>>  (self - b).abs * abs は、(self - b).abs / abs の誤りだと思うのですが、
> 
> この処理って、
>  (self-b).abs
> では駄目なんでしょうか?更にabs倍したり割ったりする意味が良く分かりません
> でした。もしかして、レシピブックの方に何か根拠が載ってたりします?
> 

レシピブックにはこれに対する説明では、
「機械イプシロン(1.0と1.0より大きい最小の数の差)」

Rubyリファレンスマニュアルでは、
EPSILON
    1.0 + Float::EPSILON != 1.0 となる最小の値

ということは、1.0が比較の基となるということなのでしょうか。
ネットで検索したらこのようなのもありました。

http://boost.cppll.jp/HEAD/libs/test/doc/floating_point_comparison.htm

レシピブックには文字列に変換して比較する方法も載っています。実用上はこれで問題な
いように思いますが、数値を比較するのに文字列に変換してしまうことが、どんなものな
のかなという気がしていましたので、この方法で可能であればいいと思って質問しました。
-- 
*********************************************
  和田稔己

In This Thread