I was writing some unit tests when I ran into some troubles… In the end
I found out the problem :
BigDecimal.new(‘15.25’) == 15.25
returns false !!
BigDecimal.new(‘15.25’).to_f == 15.25.to_f also returns false.
Substracting both values returns 1.7763… e-015
This is on ruby 1.8.6, Win32.
I’m a comp. engineer, so I know it’s ultimately related to the binary
value of 15.25 which cannot be precisely represented (without an
infinite number of bits) , but I’m still amazed that such a simple
comparison with a literal value should fail…
BigDecimal.new(‘15.25’).to_f == 15.25.to_f also returns false.
Substracting both values returns 1.7763… e-015
This is on ruby 1.8.6, Win32.
I’m a comp. engineer, so I know it’s ultimately related to the binary
value of 15.25 which cannot be precisely represented (without an
infinite number of bits) , but I’m still amazed that such a simple
comparison with a literal value should fail…
15.25 in decimal
is exactly
1111.01 in binary
Seems like a finite number of bits to me However, the
construction of 15.25 as a literal is likely something roughly (1*10^1
510^0) + (210^-1 + 5*10^-2) and those intermediate fractional
terms are problematic.
Hi, Henry
I’m writing a Ruby app that need very precise float point arithmetic.
So,
I’m using BigDecimal and test my code with unit tests, at windows xp
with
Ruby 1.8.6, also.
This seems a problem with float point number representation and
comparison.
I wrote the following method, to test what you want to:
def test_big_decimal assert_in_delta 15.25, BigDecimal(‘15.25’), 0.001
end
And… it pass. I’ve found this type here, at ruby-talk. Do a search for
a
message with “assert_equal problem” to see the reply.
Now, all my code in unit tests uses assert_in_delta, instead
assert_equal or
raw comparisons with assert and “==”.
BigDecimal.new(‘15.25’).to_f == 15.25.to_f also returns false.
Substracting both values returns 1.7763… e-015
This is on ruby 1.8.6, Win32.
I’m a comp. engineer, so I know it’s ultimately related to the binary
value of 15.25 which cannot be precisely represented (without an
infinite number of bits) , but I’m still amazed that such a simple
comparison with a literal value should fail…
15.25 in decimal
is exactly
1111.01 in binary
Seems like a finite number of bits to me However, the
construction of 15.25 as a literal is likely something roughly (1*10^1
510^0) + (210^-1 + 5*10^-2) and those intermediate fractional
terms are problematic.
irb> (self - other.to_f).abs < eps
Of course, you’d have to add a similar BigDecimal#=== to get
“%.30f” % 15.25
Well, now you’re pulling in the BigDecimal#to_f which isn’t so much a
Anybody familiar with the BigDecimal internals could check this,
please?
Well, my machine is only 32bits. You shouldn’t have a problem with
small integers. It’s when you attempt to represent some fractional
decimal values in binary. Now, if you wanted to say something about
the apparent difference between BigDecimal#to_f and String#to_f, then
you could be onto something.
I’m a comp. engineer, so I know it’s ultimately related to the binary
value of 15.25 which cannot be precisely represented (without an
infinite number of bits)
Unfortunately no, it looks like a bug. Because 15.25 is 1111.01 in
binary – exactly.
Also, it looks like it happens on 64bits machines only.
That could be because on 32-bits computations which don’t leave the
FPU are kept with 64 bits of mantissa. On 64-bits everything uses 53
bits because SSE is used for math. Of course this only applies to C
code, and may also depend on the C compiler. See http://gcc.gnu.org/PR323
for the gory details.
Seems like a finite number of bits to me However, the
construction of 15.25 as a literal is likely something roughly (1*10^1
510^0) + (210^-1 + 5*10^-2) and those intermediate fractional
terms are problematic.
It can be computed as (110^3 + 510^2 + 210^1 + 510^0) / 10^2 to
avoid those terms. I could bet that’s the bug.
Note that x / 10^2 is not the same as x * 10^-2; division is more
precise because it does not need an infinite number of bits to
represent the divisor.
Paolo, who’s relieved to see other people making the same mistakes as
him
This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.