Ruby Tips!

RubyのTipsを紹介します

浮動小数点の数値を比較する

一般的に浮動小数点は精度の問題から完全一致による比較が難しい。
一例として、1.0と、0.1を10回加算した数値は一致しない。

v0 = 1.0
v1 = 0 ; 10.times{ v1 += 0.1 }
p v0 == v1 #=> false

浮動小数点の比較を行うには、一致とみなす許容値を決めて、数値が許容値の範囲内であれば一致とみなすアプローチが必要だ。

簡単なのは、浮動小数点を文字列化してしまい、指定した桁数まで一致するかを確認する方法だ。
浮動小数点の数値の文字列化には、sprintfが使用できる。

v0 = 1.0
v1 = 0 ; 10.times{ v1 += 0.1 }
format = "%.3e" # 小数点以下3桁で比較する
p sprintf(format, v0) == sprintf(format, v1) #=> true

より細かな比較を行いたいなら、Float::EPSILONという定数を基準にして、比較を行うと良い。
この定数は1.0 + Float::EPSILON != 1.0となる最小の値を示すものだ。

v0 = 1.0
v1 = 0 ; 10.times{ v1 += 0.1 }

p (v0 - v1).abs / v0.abs <= Float::EPSILON && (v1 - v0).abs / v1.abs <= Float::EPSILON