incorrect simple floating point math

Discussion of Common Lisp
speech impediment
Posts: 36
Joined: Mon May 04, 2009 5:19 pm

Re: incorrect simple floating point math

Post by speech impediment » Fri Jun 19, 2009 5:06 pm

Harleqin wrote:Since someone mentioned financial calculations: Never do financial calculations with floats!
...
If you have precise fractions, don't use floats. The simplest way in Common Lisp is to use rationals, and convert input with RATIONALIZE and output for display with FLOAT.
You know, the RATIONALIZE and FLOAT combo seems to be the most sensible way. It's funny that I thought it was a good idea for stock prices to move from fractions to decimals. If I remember correctly, Bernie Madoff was partly responsible for stock prices being quoted in decimals. I'm not sure how the programmers at NASDAQ responded to that idea... hehe.
Harleqin wrote:For fixed-point arithmetic (like financials), just using integers as multiples of the lowest unit (e.g. cents) is also a good way.
I was pondering about this solution as well. I figure I could have a program count the decimal places, multiply them, and finally convert the results of operations back to decimal numbers, but I'm not sure how efficient it is compared to the RATIONALIZE-FLOAT combo...

Harleqin
Posts: 71
Joined: Wed Dec 17, 2008 5:18 am
Location: Bonn, Germany

Re: incorrect simple floating point math

Post by Harleqin » Sat Jun 20, 2009 9:27 am

speech impediment wrote:
Harleqin wrote:
Harleqin wrote:For fixed-point arithmetic (like financials), just using integers as multiples of the lowest unit (e.g. cents) is also a good way.
I was pondering about this solution as well. I figure I could have a program count the decimal places, multiply them, and finally convert the results of operations back to decimal numbers, but I'm not sure how efficient it is compared to the RATIONALIZE-FLOAT combo...
As long as the numbers stay inside the FIXNUM range, calculating in cents should be faster. Beyond that, it is a tradeoff between BIGNUM and RATIO arithmetic overhead.
"Just throw more hardware at it" is the root of all evil.
Svante

Paul
Posts: 106
Joined: Tue Jun 02, 2009 6:00 am

Re: incorrect simple floating point math

Post by Paul » Mon Jun 22, 2009 8:06 pm

Harleqin wrote:As long as the numbers stay inside the FIXNUM range, calculating in cents should be faster. Beyond that, it is a tradeoff between BIGNUM and RATIO arithmetic overhead.
Which is why it often is a good idea to use floats...use them as 53 bit hardware-supported big-fixnums...

simon
Posts: 16
Joined: Wed May 13, 2009 9:12 am

Re: incorrect simple floating point math

Post by simon » Mon Jun 22, 2009 10:04 pm

Paul wrote: Which is why it often is a good idea to use floats...use them as 53 bit hardware-supported big-fixnums...
Paul is quite right, the "never use floating point for financial computations" idea is overly stated. Floats are perfectly accurate and fast for integer and decimal computations like this so long as you can be certain to stay in the representable range. Which isn't always the case.

Of course these days you may not even need to resort to floats:

Code: Select all

* (log most-positive-fixnum 2)
60.0

smithzv
Posts: 94
Joined: Wed Jul 23, 2008 11:36 am

Re: incorrect simple floating point math

Post by smithzv » Tue Jun 23, 2009 1:39 am

simon wrote: Paul is quite right, the "never use floating point for financial computations" idea is overly stated. Floats are perfectly accurate and fast for integer and decimal computations like this so long as you can be certain to stay in the representable range. Which isn't always the case.
By representable range you mean a bit less than (* 1d-2 (/ long-float-epsilon)), right? The whole deal with "never use floating point for financial computations" is that money violates the pretty fundamental assumption of floating point values, that we don't care about numbers sufficiently smaller than the most significant digit. People for some reason care about pennies even when dealing with millions. Of course, the representable range on my imp seems to be around 10^14 dollars, which is a lot of money.

nuntius
Posts: 538
Joined: Sat Aug 09, 2008 10:44 am
Location: Newton, MA

Re: incorrect simple floating point math

Post by nuntius » Tue Jun 23, 2009 2:22 pm

If you must store money with a binary type, its probably better to store integers representing cents (or tenths or hundredths of a cent -- i.e. fixed-point) than to store doubles representing dollars. For addition and subtraction, it doesn't matter; but for multiplication (interest, taxes, etc), proper rounding is critical.

simon
Posts: 16
Joined: Wed May 13, 2009 9:12 am

Re: incorrect simple floating point math

Post by simon » Tue Jun 23, 2009 4:07 pm

smithzv wrote: By representable range you mean a bit less than (* 1d-2 (/ long-float-epsilon)), right? The whole deal with "never use floating point for financial computations" is that money violates the pretty fundamental assumption of floating point values, that we don't care about numbers sufficiently smaller than the most significant digit. People for some reason care about pennies even when dealing with millions. Of course, the representable range on my imp seems to be around 10^14 dollars, which is a lot of money.

No, not at all.

Recall that floating point representations are by nature capable of storing a certain range of integers exactly. In an IEEE 754 double precision float there are 53 (52 without hidden bit) bits representing the significand, and a sign bit. This is much larger than 32 bit integers. So if you are careful , it is entirely possible to to error free computations on integer values while taking advantage of both the speed and width available in your FPU. You still have to shift the computations to account for decimals. You've got a range of a little under 10^16, so even with 5 significant decimal digits (you could still count up to ten billion dollars or so, maybe drop another one for safe bound. I forget if banks use more than 5 decimal digits (i.e. 1000th of cent), adjust if needed. So this really doesn't run into trouble except at the nation level or very large financial company. But it does come up there, so you couldn't do it in any system that might be used for large transactions, or other ways to bump you out of the range (currency conversions could do it).

You do have to be careful though, because if you screw up and have any operation go outside the range of exactly representable integers, you've had it.
Last edited by simon on Tue Jun 23, 2009 4:33 pm, edited 2 times in total.

simon
Posts: 16
Joined: Wed May 13, 2009 9:12 am

Re: incorrect simple floating point math

Post by simon » Tue Jun 23, 2009 4:12 pm

nuntius wrote:If you must store money with a binary type, its probably better to store integers representing cents (or tenths or hundredths of a cent -- i.e. fixed-point) than to store doubles representing dollars. For addition and subtraction, it doesn't matter; but for multiplication (interest, taxes, etc), proper rounding is critical.

Right, when I referred to using floats, obviously I meant that you can use floats to exactly represent integers which represent (fractions of a ) cents or whatever.

However, rounding is also something you have to be careful with. FPUs generally have various possible settings for this, and different floating point standards have different ways of dealing with it. If you're writing code with currency computations, you'll need to familiarize yourself with how to make your system behave in the right way to match the definitions your system must adhere to, which as I understand it are not universal (but I could be wrong about that).

All in all, floats probably are the wrong way to go about this --- but not for the reasons mostly given here. Many programmers are fundmentally pretty confused about what floating point numbers are. Many are also a bit confused about currency computations, if they've thought about them at all. Putting those two together can't help.

simon
Posts: 16
Joined: Wed May 13, 2009 9:12 am

Re: incorrect simple floating point math

Post by simon » Tue Jun 23, 2009 4:25 pm

In case anyone is at all confused about this, I should note I really don't recommend using floats for currency computations, for several reasons. I just think if you're going to reject something, you should reject it for the right reasons, and not propagate more misunderstandings. I was also noting that with 64 bit systems the same sort of games can be played with native ints and you get the speed and width with less hassle.

If you're actually doing this stuff "for real", you probably want a BCD representation.

findinglisp
Posts: 447
Joined: Sat Jun 28, 2008 7:49 am
Location: Austin, TX
Contact:

Re: incorrect simple floating point math

Post by findinglisp » Wed Jun 24, 2009 9:05 am

simon wrote:If you're actually doing this stuff "for real", you probably want a BCD representation.
I can't think of a reason why you would prefer BCD over pure binary integers. Rounding and division problems only occur for the fractional part of the computation, so IMO the only reason to use BCD would be with the interesting BCD+floating point scheme I described previously with HP calculators, so the representation of a fractional number can be exactly the same as with standard decimal arithmetic. Even if you're doing currency calculations and you store all numbers as an integer number hundredths of a cent ($0.0001), I'm guessing you would have enough precision for basic rounding for most computations. In other words, bignums plus a large scaling factor should work for just about all financial calculations; no need to use BCD. If you're doing a long chain of calculations and want to avoid intermediate round-off, then rationals are also your friend.
Cheers, Dave
Slowly but surely the world is finding Lisp. http://www.findinglisp.com/blog/

Post Reply