BigDecimal Float worries

  • Thread starter Henrik Horneber
  • Start date
H

Henrik Horneber

Hi!

I stumbled over something while toying around with BigDecimal

require 'bigdecimal'
==>true

a = 2.12
==>2.12
b = BigDecimal.new(a.to_s).to_f
==>2.12
a == b
==>true
a = 20.12
==>20.12
b = BigDecimal.new(a.to_s).to_f
==>20.12
a == b
==>false
a.class == b.class
==>true
a.to_s == b.to_s
==>true

# in short
a == b
==>false # and then sometimes its true
a == b.to_s.to_f
==>true
b == b.to_s.to_f
==>false
#even though
b.class == b.to_s.to_f.class
==>true
a.class == b.class
==>true


seems a little strange to me.
what's going on? :)

Henrik

D:\>ruby -v
ruby 1.8.2 (2004-07-29) [i386-mswin32]
 
H

Henry T. So Jr.

seems a little strange to me.
what's going on? :)

Henrik

D:\>ruby -v
ruby 1.8.2 (2004-07-29) [i386-mswin32]

You are seeing what I consider a classic problem of computer
programming. Floating point numbers are usually represented in
computers using a format such as IEEE 754. Basically, there are so many
bits to represent the mantissa and so many bits for the exponent. The
rub is that everything is in binary. So what can be represented as an
exact decimal cannot always be represented exactly in binary (and
vice-versa). Conversion of two slightly different floating point
representations into a string for display may result in the same printed
value because the difference is so insignificant in decimal terms.

In school, we were taught never to compare floating point numbers
directly because of this. We were taught to compare them to see if they
were different by less than some threshold (which we generically called
"epsilon"). If the difference was less than epsilon then the numbers
were considered "equal" enough. The problem is that epsilon depends on
the application (i.e., depending on how much error the calculations were
willing to deal with).

This problem is also why things like the BigDecimal class are needed.
The BigDecimal class stores numbers with arbitrary precision in case the
error introduced by IEEE 754 and such formats is too significant in the
calculation.

Hope that wasn't more confusing...

Henry.
 
H

Henrik Horneber

Hi!
seems a little strange to me.
what's going on? :)

Henrik

D:\>ruby -v
ruby 1.8.2 (2004-07-29) [i386-mswin32]


You are seeing what I consider a classic problem of computer
programming. Floating point numbers are usually represented in
computers using a format such as IEEE 754. Basically, there are so many
bits to represent the mantissa and so many bits for the exponent. The
rub is that everything is in binary. So what can be represented as an
exact decimal cannot always be represented exactly in binary (and
vice-versa).
Conversion of two slightly different floating point
representations into a string for display may result in the same printed
value because the difference is so insignificant in decimal terms.

In school, we were taught never to compare floating point numbers
directly because of this. We were taught to compare them to see if they
were different by less than some threshold (which we generically called
"epsilon"). If the difference was less than epsilon then the numbers
were considered "equal" enough. The problem is that epsilon depends on
the application (i.e., depending on how much error the calculations were
willing to deal with).

This problem is also why things like the BigDecimal class are needed.
The BigDecimal class stores numbers with arbitrary precision in case the
error introduced by IEEE 754 and such formats is too significant in the
calculation.


Well yes, I was aware of that fact, that's why I was using BigDecimals
in the first place. I was _not_ aware of the fact, that
- turning a float to a string
- turning the string to a BigDecimal
- turning the BigDecimal to a float
generates such problems, just because strings and BigDecimals seemed a
'wider' type to me. Now that you mention it, it is kind of obvious that
there still are these problems, because of different representations.
Strange how such perceptions of 'wider' or 'more precise' can fool you...


Thanks!

Henrik
 
R

Robert Klemme

Henrik Horneber said:
Well yes, I was aware of that fact, that's why I was using BigDecimals in
the first place. I was _not_ aware of the fact, that
- turning a float to a string
- turning the string to a BigDecimal
- turning the BigDecimal to a float
generates such problems, just because strings and BigDecimals seemed a
'wider' type to me. Now that you mention it, it is kind of obvious that
there still are these problems, because of different representations.
Strange how such perceptions of 'wider' or 'more precise' can fool you...

Well, the weakest link in the chain is the crucial one and in this case it's
the float. So as long as the values are converted into a float once
somewhere in the process you can bet that == will fail at some point. :)

Regards

robert
 
H

Henrik Horneber

Robert said:
Well, the weakest link in the chain is the crucial one and in this case
it's the float. So as long as the values are converted into a float
once somewhere in the process you can bet that == will fail at some
point. :)

This is what it boils down to, agreed. I guess I just can't see the
forrest because of all those trees.

Henrik
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,776
Messages
2,569,603
Members
45,189
Latest member
CryptoTaxSoftware

Latest Threads

Top