Reputation: 11040
I have this spec that checks for the expected number:
expect(animal_cost).to eq(0.7771118644067795e5)
I get an error that says:
expected: 77711.18644067795
got: 0.7771118644067795e5
As you can see, the number I got is the same as the one I expected so I'm confused why this is failing. How can I set the spec?
animal_cost.class
is a BigDecimal.
Upvotes: 7
Views: 2861
Reputation: 50057
The best way to verify floats using rspec is to use the be_within
matcher. Floats cannot be represented completely mathematically accurate in binary. There are bound to be some rounding errors.
In your case one would write:
expect(animal_cost).to be_within(0.001).of(0.7771118644067795e5)
Upvotes: 6
Reputation: 114238
[animal_cost] equals
0.7771118644067795e5
[...] it's aBigDecimal
It's a floating point issue. Your BigDecimal
with a value of 0.7771118644067795e5 has an exact value of:
77711.18644067795
The float 77711.18644067795
on the other hand has an actual value of: (like most languages, Ruby truncates floats)
77711.186440677949576638638973236083984375
Depending on the comparison, these values might or might not be treated as "equal":
d = BigDecimal('0.7771118644067795e5')
f = 0.7771118644067795e5
d == f #=> true
f == d #=> true
d.eql?(f) #=> true
f.eql?(d) #=> false
The latter returns false
because that's how Float#eql?
works:
eql?(obj) → true or false
Returns
true
only ifobj
is aFloat
with the same value asfloat
.
In order to make the test pass with the exact value, you should use a BigDecimal
instead of a float:
expect(animal_cost).to eq(BigDecimal('0.7771118644067795e5'))
Personally, I'd avoid such examples because you're (apparently) copying the result into the expectation. It's not at all obvious whether this value is correct or not. (a "cost" with 11 decimal places seems wrong to me) Try to change your example data to get a comprehensible result and maybe also a "whole" number like e.g. 70,000.
Upvotes: 4