From: Robert Klemme Date: 2008-08-05T00:07:08+09:00 Subject: Re: Whose fault is my problem? 2008/8/4 The Podman : [Vectors with floats in them are not equal according to ==.] > So who is to blame? Me, for not realising that the objects I'm trying to > compare have two floats somewhere in some array and that I should > descend into these objects and manually compare their internal data? I am afraid, yes. > Whilst in this case it's rather explicit where the problem is, as it's > just a math's style Vector of Floats, in most cases I won't know the > implementation details of the objects, I'm dealing with, right? And if > those objects happened to bring in a Floating point number somewhere, > how am I to know that a != b purely because of this issue? > > Or is it the fault of Vector, for not realising that it'll often have > floating point numbers stuffed into it and that it should do something a > bit cleverer that array == array? No, because a Vector cannot make any assumptions about when you as a user would consider two floats equivalent (i.e. what is the maximum delta you would accept - or is it a factor? Does it depend on the number's sizes etc.). > Or is it the fault of Float, for not realising that Ruby programmers > shouldn't have to care about trivial things like two floats being > 0.00000003e-17 out? Same here, Float cannot know what your requirements are. In light of this for library code it is the most reasonable thing to implement == as binary identity for floats. > When I get home I'm going to have to make my unit tests care about delta > difference between two floating point numbers (infact, there's a method > to help me do that...), but annoyingly I'm going to have to start > plucking data out of an object and essentially re-implement == between > two Vectors. Depending on the lib you might as well be able to calculate the abs difference of the two Vectors and assert that the result is less than a Vector with all deltas that you define as constant somewhere. > Whilst this will fix my problem in this case, I imagine it > won't fix other people's problems in the general case. So, Ruby fans, > what should be done? Should this problem exist in a language like Ruby? Unfortunately there is no general one size fits all solution when it comes to floating point number equivalence. This is the same for all languages - apart from algebraic tools such as Mathematica which work quite different internally. > Or not? After all, if it quacks like a 27.8 and displays like a 27.8, > shouldn't Ruby treat it as 27.8? Well it does, but "27.8" might not be the full truth. You need to keep in mind that "27.8" is a _decimal representation_ while internally the number is stored in a _binary representation_. Conversion between the two introduces errors which is the reason for the phenomena you (and a lot others) are seeing. For results that resemble more closely what you would expect you could use BigDecimal. 17:02:08 bas$ irb -r bigdecimal Ruby version 1.8.7 irb(main):001:0> a = BigDecimal.new '37.8' => # irb(main):002:0> b = BigDecimal.new '27.8' => # irb(main):003:0> a - b => # irb(main):004:0> (a - b).to_s => "0.1E2" irb(main):005:0> (a - b) == 10 => true irb(main):006:0> "%10.3f" % (a - b) => " 10.000" irb(main):007:0> "%.3f" % (a - b) => "10.000" Kind regards robert -- use.inject do |as, often| as.you_can - without end