-
Type: Task
-
Resolution: Done
-
Affects Version/s: None
-
Component/s: None
-
Labels:
I'm getting some weird behavior from Mongoid::Extensions::Time when Floats are passed to it. Rounding errors..
It doesn't happen on every float, but at least those with decimals. I haven't been able to determine the exact requirements for a float to be subject to this rounding error.
The problem occurs in Mongoid v3.0.14 and all versions after that.
The behavior was introduced in this commit: https://github.com/mongoid/mongoid/commit/b9aee40ef2a86c56fc72020b2064087c5e968502
In this file, this line.
This is what happens, code with an example spec:
Mongoid 3.0.13
The floats given to the class are the same ones I get back.
class TimeTest include Mongoid::Document field :time, :type => Time end TimeTest.new(:time => 1.1).time.to_f => 1.1 TimeTest.new(:time => 2.1).time.to_f => 2.1 TimeTest.new(:time => 3.1).time.to_f => 3.1 TimeTest.new(:time => 4.1).time.to_f => 4.1 TimeTest.new(:time => 5.1).time.to_f => 5.1 TimeTest.new(:time => 6.1).time.to_f => 6.1 TimeTest.new(:time => 7.1).time.to_f => 7.1 TimeTest.new(:time => 8.1).time.to_f => 8.1 TimeTest.new(:time => 9.1).time.to_f => 9.1 TimeTest.new(:time => 10.1).time.to_f => 10.1 TimeTest.new(:time => 11.1).time.to_f => 11.1 TimeTest.new(:time => 15.1).time.to_f => 15.1 TimeTest.new(:time => 20.1).time.to_f => 20.1 TimeTest.new(:time => 25.1).time.to_f => 25.1
Mongoid 3.0.14
Now the floats given to the class are modified, they lose their precision.
# Using the same class TimeTest.new(:time => 1.1).time.to_f => 1.1 TimeTest.new(:time => 2.1).time.to_f => 2.1 TimeTest.new(:time => 3.1).time.to_f => 3.1 TimeTest.new(:time => 4.1).time.to_f => 4.099999999 # => So here it differs from the old behavior TimeTest.new(:time => 5.1).time.to_f => 5.099999999 TimeTest.new(:time => 6.1).time.to_f => 6.099999999 TimeTest.new(:time => 7.1).time.to_f => 7.099999999 TimeTest.new(:time => 8.1).time.to_f => 8.099999999 TimeTest.new(:time => 9.1).time.to_f => 9.099999999 TimeTest.new(:time => 10.1).time.to_f => 10.099999999 TimeTest.new(:time => 11.1).time.to_f => 11.099999999 TimeTest.new(:time => 15.1).time.to_f => 15.099999999 TimeTest.new(:time => 20.1).time.to_f => 20.1 TimeTest.new(:time => 25.1).time.to_f => 25.1
Environment
Running on Ruby 1.9.3p327. Example is made in a Rails 3.2.11 app with MongoDB 2.2.2.
Example spec
Very much an example spec: (Not sure how to exactly test all kinds of floats which could trigger this behavior.)
context "when given a float" do it "stored the float accurately" do Time.mongoize(2500.1).to_f.should eq(2500.1) end end
Result:
1) Mongoid::Extensions::Time.mongoize when given a float stored the float accurately Failure/Error: Time.mongoize(2500.1).to_f.should eq(2500.1) expected: 2500.1 got: 2500.099999999 (compared using ==) # ./spec/mongoid/extensions/time_spec.rb:189:in `block (4 levels) in <top (required)>' Finished in 0.14754 seconds 44 examples, 1 failure
In conclusion
Is this expected behavior after this change or not?
I realize this is miliseconds work, but I'd like to have my data the way I stored them.