T
The Podman
I've recently started to write an appliaction in Ruby. It's the first
time I'm using the language. Infact, the only reason I'm using it is
because it's all my friends EEE laptop had on it at the time (What?!
No gcc!!?) Still, I've started now so I'll stick with it. Anyway, after
reading the the pickaxe book from cover to cover, I decided to change my
unit tests from a bunch of "puts blahblah, stuff" to those lovely
Test::Unit modules..... and then I encountered a problem.
As some point, I'm asking Ruby to assert_equal(a,b), where a and b are
Vectors (from the matrix.rb file). Unfortunatley one test fails,
specifically in the case where Vector[27.8, 0.0] does not equal
Vector[27.8, 0.0]. After much head scratching and playing about with the
debugger, I realised it's the age old problem of floating point
comparison. For some reason I just didn't expect to have to worry about
this in Ruby! Annoyingly, I don't know how to go about "fixing" my
problem. and my problem is this:
* I want to unit test.
* I want to use assert_equal, because I'm using it for the other 20 or
so tests called by the same looping iterator and it works just fine for
these :}
* Unfortunatley assert_equals calls == on the two objects in question.
* These two objects (in this case) are Vectors. Vector == Vector simply
hands of equality checking to array's == method, asking if Vector.array
== Vector.array.
* Array == iterates though both arrays and uses == between the elements.
* Float == Float does not perform any delta difference checking. In a
way, this is expected. In another way, it's not.
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?
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?
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?
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. 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?
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?
Cheers,
Pod.
ps, you can emulate the problem with a simple bit of "p 37.8 - 10 ==
27.8" -> false.
time I'm using the language. Infact, the only reason I'm using it is
because it's all my friends EEE laptop had on it at the time (What?!
No gcc!!?) Still, I've started now so I'll stick with it. Anyway, after
reading the the pickaxe book from cover to cover, I decided to change my
unit tests from a bunch of "puts blahblah, stuff" to those lovely
Test::Unit modules..... and then I encountered a problem.
As some point, I'm asking Ruby to assert_equal(a,b), where a and b are
Vectors (from the matrix.rb file). Unfortunatley one test fails,
specifically in the case where Vector[27.8, 0.0] does not equal
Vector[27.8, 0.0]. After much head scratching and playing about with the
debugger, I realised it's the age old problem of floating point
comparison. For some reason I just didn't expect to have to worry about
this in Ruby! Annoyingly, I don't know how to go about "fixing" my
problem. and my problem is this:
* I want to unit test.
* I want to use assert_equal, because I'm using it for the other 20 or
so tests called by the same looping iterator and it works just fine for
these :}
* Unfortunatley assert_equals calls == on the two objects in question.
* These two objects (in this case) are Vectors. Vector == Vector simply
hands of equality checking to array's == method, asking if Vector.array
== Vector.array.
* Array == iterates though both arrays and uses == between the elements.
* Float == Float does not perform any delta difference checking. In a
way, this is expected. In another way, it's not.
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?
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?
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?
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. 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?
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?
Cheers,
Pod.
ps, you can emulate the problem with a simple bit of "p 37.8 - 10 ==
27.8" -> false.