Major Addition Bug?

L

Lloyd Zusman

I'm not sure how well known this is. Is it well known as being a problem
or well known as in "you should never do this sort of thing".

Seems to present a major problem if you want to deal with financial
figures, for example. Are there any workarounds?

I have been programming for 35 years, and during this time, I keep
seeing members of the financial community writing programs that do money
math with floating point numbers. Several times in my career we had to
rewrite code that mis-used floating point in this way, when people
finally realized that they can't get exact results.

One way around this in Ruby is to use the BigDecimal class. It allows
arbitrary precision math to be performed. There are other solutions, as
well. For example, the Rational class can also be used for financial
calculations.
 
P

Phil Tomson

Phil said:
[Floating point imprecision seems] to present a major
problem if you want to deal with financial figures, for
example. Are there any workarounds?

Financial calculations aren't done in floating point. There are various
number formats that are used, but they all boil down to some form of integer
arithmetic. For example, fixed point decimal may be used, where the value
$625.91 is represented as the integer 62591 with a scaling factor of two
decimal places. In other words, the arithmetic is actually done in pennies,
not dollars.

-Mike



This seems to be the 100,000th post to Ruby-talk (at least the English
version).

What has our player won?

BTW: Yes, doing financial calculations in pennies seems to make a lot of
sense.

Phil
 
H

Hal Fulton

Sean said:
Well known? I had no idea this bug existed until I wrote a line of code that
double-checked the arithmetic from a different app. I have code all over
doing simple arithmetic like this. Ruby can't add 3 simple numbers? I don't
mean to be disproportionately negative, but that shakes my faith more than a
little. It's just simple arithmetic. How old is this bug? When is it
getting fixed?

Offhand I'd say this bug dates back to the 1940s, and isn't
getting fixed any time soon.

Seriously, I think it's a matter of trying to store an infinite
number of digits in a finite number of bits.

For a daily life example: How many digits does it take to store
"1/3" exactly? 0.333333...



Hal
 
M

Mohammad Khan

I guess, you guys are missing the point,

in real life you can't have exact answer of 1/3 + 2.3 + 1.3
but you can have exact answer of 625.91 + 900.00 + 22.00

Mohammad




----- Original Message -----
From: "Hal Fulton" <[email protected]>
To: "ruby-talk ML" <[email protected]>
Sent: Wednesday, May 12, 2004 3:15 PM
Subject: Re: Major Addition Bug?
 
A

Aredridel

I'm not sure how well known this is. Is it well known as being a problem
or well known as in "you should never do this sort of thing".

Seems to present a major problem if you want to deal with financial
figures, for example. Are there any workarounds?

Short answer: use rational numbers -- slower, but works.

Long answer: For finance, specifically, use integer numbers of pennies,
at least for US currency, or some other fixed-point format. It has
error, but it's an accepted, standard error. According to most
accountants, 0.005 + 0.044 is 0.05.

Ari
 
H

Hal Fulton

Lloyd said:
In 1969 I took a course called Introduction to Computer Programming. In
one of the early chapters of the textbook, we learned about a concept
called "floating point arithmetic". One aspect of this topic that was
drilled into us is the way that floating point arithmetic does not yield
exact results.

I want to add that this concept, which is so basic to the understanding
of programming that it was taught in an introductory course before we
even wrote a line of code, was old information even in 1969.

This basic concept of floating point arithmetic is every bit as
pertinent today as it was in 1969 and the years prior to that. Did you
actually not learn this concept before starting to program in Ruby?

I don't know Sean's situation or background, but let me point out that
many people on this list are not of an actual computer science
background. Best know example: David Alan Black, though very
knowledgeable in computing, actually comes from a humanities background
if I'm not mistaken.

Of course, overall I agree with you. I'd be disappointed if I found that
someone with a degree in computer science (or even 2-3 semesters) didn't
understand this fact.

But some people on this list are self-taught programmers. They may never
have had a single class in computer science. No discrete structures, no
digital systems, no operating systems, no analysis of algorithms.

And while I agree that this fact of floating-point life is an essential
concept for any serious programmer, it's not the sort of thing you learn
when you're self-taught. Hmm, maybe there should be a book of that stuff
for the self-taught programmer. (/me thinks and scribbles)

Anyhow, we have a wide diversity of ages and experience levels here.
Pretty cool, I think.

Some people on this list have not even finished high school yet, I
am guessing...


Cheers,
Hal
 
H

Hal Fulton

Mohammad said:
I guess, you guys are missing the point,

in real life you can't have exact answer of 1/3 + 2.3 + 1.3
but you can have exact answer of 625.91 + 900.00 + 22.00

Only if you build a computer that works in decimal. In binary,
625.91 is as inexact as 1/3 is in decimal.


Hal
 
G

Guillaume Marcais

Only if you build a computer that works in decimal. In binary,
625.91 is as inexact as 1/3 is in decimal.

Well, my HP48 calculator's processor is able to do math in binary or
decimal. The real numbers are stored in memory in decimal and the
operations by default made in decimal. It doesn't make my calculations
any more precise, but it made (some of) the rounding errors less
suprising.

But Ruby doesn't compile on my HP48 :(

Guillaume.
 
S

Sean O'Dell

Short answer: use rational numbers -- slower, but works.

Long answer: For finance, specifically, use integer numbers of pennies,
at least for US currency, or some other fixed-point format. It has
error, but it's an accepted, standard error. According to most
accountants, 0.005 + 0.044 is 0.05.

It's great to get some validation on some of my ancient rounding problems. It
never occurred to me that the problem rested with a fundamental issue in the
floating point processor. I had always thought I was doing something wrong
or the compiler was funky.

I've done a lot of financial stuff using long integers and pennies. It's nice
to hear that's a method others use, and recommend.

All: Don't worry about busting my chops. It was earned. I am just as likely
to nail someone for their ignorance. Live and learn.

Anyway, upside: this didn't cost me a dime in tuition and now I know. =)
Suckers! j/k

Sean O'Dell
 
J

John W. Kennedy

Sean said:
Funny though, if I set a variable to 1547.91 exactly, it is represented just
fine.

No it isn't.

ruby -e "puts sprintf('%20.13f', 1547.91)"
I had to massage my floating point math in C/C++ a lot many years ago, but I
always assumed it was a flaw in the MS compiler,

Kindly get in touch with your C/C++ teacher and shoot him. What we are
talking about here is a basic characteristic of nearly all computers
made since the mid-1960's, and a large fraction of the computers made
before then.

Only a handful of languages support exact decimal arithmetic (COBOL,
PL/I, Ada, Java, and REXX come to mind), and IBM zSeries and iSeries
mainframes are about the only modern machines capable of doing decimal
arithmetic in hardware.
 
S

Sean O'Dell

Well, my HP48 calculator's processor is able to do math in binary or
decimal. The real numbers are stored in memory in decimal and the
operations by default made in decimal. It doesn't make my calculations
any more precise, but it made (some of) the rounding errors less
suprising.

Sort of makes me wonder if someone somewhere doesn't make a replacement FPU
that does all of its calculations as real decimal values, or at least
automatically corrects rounding errors.

Sean O'Dell
 
J

John W. Kennedy

Lloyd said:
This basic concept of floating point arithmetic is every bit as
pertinent today as it was in 1969 and the years prior to that.

Careful. Decimal floating point is not, per se, a contradiction in
terms. Many machines had it in the 1950s, and some systems still
support it in software to this day.

--
John W. Kennedy
"You can, if you wish, class all science-fiction together; but it is
about as perceptive as classing the works of Ballantyne, Conrad and W.
W. Jacobs together as the 'sea-story' and then criticizing _that_."
-- C. S. Lewis. "An Experiment in Criticism"
 
S

Sean O'Dell

Kindly get in touch with your C/C++ teacher and shoot him.

I will go so far as to have a stern talk with Herbert C. Schildt for not
mentioning the floating point issue in any of the many books I bought which
were written by him, but I refuse to shoot him.

Sean O'Dell
 
S

Stephan Kämper

Hal said:
Seriously, I think it's a matter of trying to store an infinite
number of digits in a finite number of bits.

For a daily life example: How many digits does it take to store
"1/3" exactly? 0.333333...

SCNR, but:

irb(main):001:0> 1/3
=> 0

*That* result fits into a single bit. ;-)

But in general there's not much to add to this thread, but to summarize it:

- For financial calculations use specialised classes (which should
handle different currencies, BTW)
- If you *need* a higher number of digits use BigDecim (which is
documented in the 'Ruby Standard Library Documentation' available
at http://www.ruby-doc.org/downloads/stdlib/ )
- Never, repeat *never* compare floats with == or other operators like
that. Define some kind of accuracy, say epsilon and use a usual metric
like this:
( a_value - something_else ).abs < epsilon
- Don't use == to compare floats and last but not least
- Comparing floats with == is a Bad Thing.

Well, that's it - more or less.

Happy rubying,

Stephan
 
S

Stephan Kämper

Guillaume said:
On Wed, 2004-05-12 at 15:35, Hal Fulton wrote:

But Ruby doesn't compile on my HP48 :(

I wish it did, too. A cool thing the HP48.

Cheers

Stephan
 
G

gabriele renzi

il 12 May 2004 19:00:24 GMT, (e-mail address removed) (Phil Tomson) ha
scritto::

This seems to be the 100,000th post to Ruby-talk (at least the English
version).

damn, I got distracted by my brother or I would have been the one!

Now I have to wait for 1_000_000 to put my name in the history :/
 
J

Joel VanderWerf

gabriele said:
il 12 May 2004 19:00:24 GMT, (e-mail address removed) (Phil Tomson) ha
scritto::





damn, I got distracted by my brother or I would have been the one!

Now I have to wait for 1_000_000 to put my name in the history :/

It's ironic that the 100_000th post was in a discussion of decimal
arithmetic.

Shouldn't we find powers of 2 more significant? The next one is 2**17,
or 131072, so we all have a while to prepare a discussion on some binary
topic like, oh, say, bitwise ops.
 
H

Hal Fulton

Joel said:
It's ironic that the 100_000th post was in a discussion of decimal
arithmetic.

Shouldn't we find powers of 2 more significant? The next one is 2**17,
or 131072, so we all have a while to prepare a discussion on some binary
topic like, oh, say, bitwise ops.

If memory serves me, #12345 was an announcement that the numbers would
no longer appear in the subject line. That always amused me.


Hal
 
M

Mark Hubbart

I guess, you guys are missing the point,

in real life you can't have exact answer of 1/3 + 2.3 + 1.3

Oh, but you can! you just need to choose an appropriate radix. Radix 30
will do:

1/3 + 2.3 + 1.3 becomes:

0.a + 2.9 + 1.9 = 3.s

Your answer is 3.s radix 30. This translates to approximately 3.93333
radix ten (decimal); or about 11.11101 radix 2 (binary).

In real life, number stay fractions. Decimal notation is only precise
for numbers whose denominators factor out to twos and fives. Binary
(and hence floating point arithmetic) is only precise for fractions
whose denominator is factorable into twos. So unless your decimal
number ends in .25, .125, and so on, you're out of luck.
but you can have exact answer of 625.91 + 900.00 + 22.00

Only when using base ten, which computers usually don't.

cheers,
--Mark
 
M

Mark Hubbart

This got me thinking. It would be really cool to have a currency
class that allowed for conversion between currencies using some
web-retrieved table of current conversion rates. Rates would be
cached after first being retrieved and would be updated once a day or
so.

That's a very cool idea. If you do decide to do this:
http://www.imf.org/external/np/tre/sdr/db/rms_fpt.cfm

Current currency exchange rates, from the IMF. In CSV form. Averaged
over the last five days, it appears. Apple's builtin calculator app
uses it to update it's currency tables, I believe.

cheers,
--Mark
 

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

No members online now.

Forum statistics

Threads
474,145
Messages
2,570,826
Members
47,371
Latest member
Brkaa

Latest Threads

Top