The Trouble With Rounding Floats
lukfil writes "We all know of floating point numbers, so much so that we reach for them each time we write code that does math. But do we ever stop to think what goes on inside that floating point unit and whether we can really trust it?"
What about encoding floats as a pair of ints or longs: one to express the numerical value, and the other its tenth power; id est, decimal arithmetic?
Office Space
hmm...
If history repeats itself, why can't we study the future?
This is why I use the decNumber library from IBM.
l The decNumber library implements the General Decimal Arithmetic Specification[1] in ANSI C. This specification defines a decimal arithmetic which meets the requirements of commercial, financial, and human-oriented applications.
http://www2.hursley.ibm.com/decimal/decnumber.htm
The library fully implements the specification, and hence supports integer, fixed-point, and floating-point decimal numbers directly, including infinite, NaN (Not a Number), and subnormal values.
The code is optimized and tunable for common values (tens of digits) but can be used without alteration for up to a billion digits of precision and 9-digit exponents. It also provides functions for conversions between concrete representations of decimal numbers, including Packed Decimal (4-bit Binary Coded Decimal) and three compressed formats of decimal floating-point (4-, 8-, and 16-byte).
If you are actually concerned about rounding and precision, use decimal instead.
I am Intel of Borg, you will be approximated.
There have been many examples, such as the original pentium bug. Of course, there was a bug in Windows Calc, it was 2.01 - 2.0 = 0 (If I remember correctly).
Fight Spammers!
Apparently the author of the article didn't read the stories in RISKS that he cited. In particular, the 'pensioners being shortchanged' one talks about them not being paid interest on 'float'-- cash flow on transactions in progress. This has little to do with floating point numbers.
Similarly, the spacecraft problem mentioned is one of an errant cast, not because of dilution of precision in floating point calculations.
The author could really pick his examples better-- as mistakes in numerical programming happen often and are often of great import.
This is not a new problem. Or an unsolved one. Is there any modern programming language that does not supply a data type or library with exact decimal arithmetic support? Using a float to represent monetary amounts and expecting them to be free of rounding errors is as stupid as using integers to store zip codes and wondering where the leading zeros went from all the addresses in New England. If you can't be arsed to choose the right data type get out of the business.
Sigs? Sigs? We don't need no steenkin' sigs.
Would certainly be a real kicker to find out that these tiny miscalculations caused everyone to pay more tax than they needed to. Where's my refund check?!
He talks about scientific applications, but actually very few scientific calculations are sensitive to rounding error. Remember, they sent astronauts to the moon using slide rules. Generally for scientific applications, you just don't want to roll your own crappy subroutines for stuff like matrix inversion; use routines written by people who know what they're doing. (And know the limitations of the algorithm you're using. For example, there are certain goofy matrices that will make a lot of matrix inversion algorithms blow chunks.)
For business apps, the classic solution was to use BCD arithmetic. But today, is it more practical (and simple) just to use a language like Ruby, that has arbitrary-precision integers, so you can just store everything in units of cents? A lot of machines used to have special BCD instructions; do those exist on modern CPUs?
Find free books.
Should read, "write code that does arithmetic." Don't kid yourself and think you are doing anything remotely close to
real mathematics.
This happens more often than you might think. I used to work for a large American software corp. One of their products which I had the pleasure of being on one of two teams who were working on it, had an accounting portion that used floating point columns in our DB schema and in code. I just was kind of disgusted and a little disturbed after finding this software's used by some pretty large organizations to track assets, etc.
This reminds me of something someone I knew said once: you don't really have to be intelligent to work in this industry or even get through school, just like everything else in life, it seems that brute force is enought to win most of the time.
why run from Vincenzo?
float (and the big brother double) is inaccurate. Its no surprise. A 32-bit Float is but a single simple tool in a programming language. If anyone is surprised by how Floats behave then they are, most likely, inexperienced.
You don't start addressing a problem in software just by assuming Float or Double will magically fill every need. An experienced programmer needs to have a knowledge of how to use, and how not to use, the programming tools at hand. TFA about floating point numbers is very introductory (at the end it mentions that the next article will tell us how to "avoid the problem"... I assume it will go on to cover some basic idioms.) In a way it misses the point: Floating-point rounding is not a "problem". Floats and Doubles always do their job, but you have to know what that job is! The behaviour of floating point numbers should not be a big surprise to a seasoned coder.
For example: You can't use float or double to store the numerical result of a 160-bit SHA-1 hash... you have to use the full 160 bits. (Duh, right?) So, if you use a mere 32 bits (float) or 64 bits (double) to store that number, you are going to sacrifice a lot of accuracy!
I did a model of universal expansion using only ints that proved conclusively that the universe is 6 years old.
Friends don't help friends install M$ junk.
We have the same problem in everyday numbers. Try representing 1/3 in any finite number of digits. You can't. The big thing about floating-point numbers that trips people up is that we're used to thinking in base 10. Floating-point numbers in computers typically aren't in base 10, they're in base 2. The rounding problem he describes is simply us getting confused and wondering why a fraction with an exact representation in base 10 doesn't have an exact representation in base 2. The obvious solution is the one he alludes to at the end: don't use base 2. Computers have had base-10 arithmetic in them for decades, in fact the x86 family has base-10 arithmetic instructions built in (the packed-BCD instructions). COBOL has used packed-BCD since it's beginning, which is why you don't find this sort of calculation error in ancient COBOL financial packages running on mainframes.
Due to the efforts of Willam Kahan at U.C. Berkeley, IEEE 754 floating point, which is what we have today on almost everything, is far, far better than earlier implementations.
Just for starters, IEEE floating point guarantees that, for integer values that fit in the mantissa, addition, subtraction, and multiplication will give the correct integer result. Some earlier FPUs would give results like 2+2 = 3.99999. IEEE 754 also guarantees exact equality for integer results; you're guaranteed that 6*9 == 9*6. Fixing that made spreadsheets acceptable to people who haven't studied numerical analysis.
The "not a number" feature of IEEE floating point handles annoying cases, like division by zero. Underflow is handled well. Overflow works. 80-bit floating point is supported (except on PowerPC, which broke many engineering apps when Apple went to PowerPC.)
Those of us who do serious number crunching have to deal with this all the time. It's a big deal for game physics engines, many of which have to run on the somewhat lame FPUs of game consoles.
Floating point numbers are an approximation. So why would you use them for an exact answer? Duuuuhhhhhh
They're convenient while programming, but they can certainly be a PITA to use properly. First they don't compare properly (you can't test equality), and if you have to do multiplatform programming transferring floats, they had better be stored in standard format (which can have a nasty side-effect of slowing down your floating point arithmetic since after each operation the unit has to return it back to IEEE format from machine native).
I've seen programmers who never realized these facts and had them ask why their code didn't work (they stored statistics gathered from a monitoring unit on an ARM Linux embedded board, transferred them to a PC, and had nonsensical results). Altering the way they serialized their floats and doubles fixed that issue. And nevermind that processing a float on different architectures can have slightly different results (or big results, depending on how you write your code). I guess some people treat floating point numbers the same way as integers, when they're more approximation than anything.
Or you can write code like this guy - http://thedailywtf.com/forums/thread/71883.aspx
UIEEE754 specifies exact results. There is no room for interpretation. That means it is not the FPU we should be worried about but IEEE764. However I find that IEEE754 is quite well done.
On the other hand, people that programm with floats and do not know or understand IEEE754 are asking for trouble. But that is true with every type of library. Knowledge and insight can only be replaced by more knowledge and greater insight. El-Cheapo outsourcing to India or hiring people without solid CS skills as programmers is asking for trouble.
Most ACs are not even worth the keystrokes to insult them. Be generically insulted by this and ignored otherwise.
I got to about the 3rd sentence before the hamster running on the wheel in my head fell off and, in a daze, started pooping everywhere. That happens anytime I read something math related. Good thing math is just a fad.
Did they stop teaching this stuff in first year university? As for the person who posted: "Try representing 1/3 in any finite number of digits" well, you and I just did using 2 integers.
The use of transforms for handling numerical calculations is an old trick. It is probably best-known in its use as a very quick way to multiply or divide using logarithms and a slide-rule, prior to the advent of widely-available scientific calculators and computers. Nonetheless, devices based on logarithmic calculations (such as the mechanical CURTA calculator) can wipe the floor with most floating-point maths units - this despite the fact that the CURTA dates back to the mid 1940s.
It's a small world and it smells funny; I'd buy another if it wasn't for the money; Take back what I paid (SoM)
The second part of the question can be easily answered. Compile the computer program in two ways. First, set the compiler to not use the floating-point unit (FPU). Just generate the instructions for explicitly doing the floating-point computations in software. Run the compiled code and save the results.
Second, set the compiler to explicitly use the FPU. Generate FPU instructions to do the floating-point computations in hardware. Run the compiled code and save the results.
The results should be identical. If they are not identical, then either the compiler has a (software) bug or the FPU has a (hardware) bug. If you are using GCC without optimization, then the FPU probably has a hardware bug. GCC is quite reliable when it is used without any optimization.
The author goes on and on about how floating point numbers are inaccurate, and unable to precisely represent represent real values, like this is something new, or even something different from the number approximations we normally use.
The reason the examples the author cites can't be represented precisely is that floating point numbers are ultimately represented as base-2 fractions, and there are a bunch of finite-length base-10 fractions that don't have a non-repeating base-2 representation. Guess what? We have *exactly* the same problem with the base-10 fractions that everyone uses all the time. Show me how you write 1/3 as a decimal!
The problem isn't that floating point numbers are inherently problematic, the problem is that we typically use them by converting base-10 numbers to them, doing a bunch of calculations and then converting them back to base 10. Floating point rounding isn't an unsolved problem -- floating point rounding works perfectly, and always has. It's just that the approximations you get when you round in base 2 don't match the approximations you get when you round in base 10.
Bottom line: If you care about getting the same results you'd get in base 10, do your work in base 10. This is why financial applications should not use floating point numbers.
Note to ACs: I usually delete AC replies without reading them. If you want to talk to me, log in.
I wouldn't call it CS101. In CS101 you learn, of course, that computers are finite machines and can't hold infinite values exactly (ex PI). Going into the precision detail would require a course in Numerical Analysis. Since you know there will always be some error, one of the components of Numerical Analysis is figuring out what the error will be. From that you can determine what error threshhold is acceptable and perform the calculations.
and
When bad things happen to good numbers (as well as Becker's other floating-point columns on that same page)
Or more importantly, do you math in a system where the level of precision (number of significant digits) is far greater than the answers you require.
pardon my ignorance but why does the problem exist today? can't it be fixed? what is the actual effect to us (since in the forum, the examples given in the article are false)? (links will be helpful.)
when i use my calculator, it doesn't give rounded off numbers. i suspect lots of programs will have problems with rounding off but i don't seem to notice it. is it that insignificant?
Live your life each day as if it was your last.
This is why I use DECIMAL and not FLOAT in MySQL. Problem solved. I'm not a big fan of floats, the extreme precision that they seem to have is mostly an illusion.
'Floating point numbers'
as opposed to
'Computer implementation of the storage and manipulation of floating point numbers'
Only the latter might be suspect, depending on the implementation.
Whatever happened to what used to be known as 'scientific notation' for what are also called 'real numbers'? Eg, you store the mantissa (eg "37") and the exponent (eg -2) and there is no approximation involved, although the mantissa might have a set maximum length, so you might have trouble storing, for example 1.000000000000000000000001 if the mantissa had a maximum length of ten.
If we think back to the good old days of the first Gulf War and all that, we might remember the Patriot missile and what a dismal failure that was. Part of the problem there was that the missile's clock values were such that they would not convert to base 2 (and hence to float) accurately and so the tracking was off and lots of expensive misses happened. If you recall, lots of US soldiers died when a Scud that theoretically ought to have been shot down hit their barracks.
;)
As usual, it's not just one thing that screws everything up, not even in the narrow confines of the Patriot's software problem. Here's a short write-up on that math/software part of it. There were other issues with the Patriot but that'd be blatant off-topic flamebait.
Even as you read this, your pants are strangling your loins! Aaa!
I remember an old question from grad school: Why might you add a bunch of floating point numbers starting with the smallest? The answer is because floating point decimal accuracy goes down the larger the characteristic (non-decimal) is, so add the small numbers to get a larger characteristic before you add the larger numbers in. If you add the big numbers first, adding the small numbers might not change the intermediate sum. Of course, real-world floating point error in numerical algorithms is much more subtle. On the other hand, software engineering errors are often not subtle at all, so maybe things balance out. :)
Is GMP similar to that? I used it to approximate the Poisson function for BER calculations. Pretty easy to use.
Welcome to a very poor article on what's been taught in early Comp Sci for many many years.
Any serious developer of business software knows all about this and avoids floating point at all cost for financial calculations. Scientists however do use them carefully since the math they do is usually much more performance (speed) sensitive and the calculations are a little more complex than what tends to be done on the business side (ie _most_ business calcs are relatively simple).
These posts express my own personal views, not those of my employer
I found this out years ago, and took it so far as to try to find a solution to the problem. I took it on as part of my senior thesis in college and worked to develop a way to, essentially, create a class that stored numbers using a numerator and denominator which could be of invariable size (think BigInteger numerator, BigInteger denominator, but using C++).
The drawbacks include that it is somewhat complex, most especially with the division (and somewhat, though to a lesser degree, multiplication), as well that it is not as efficient as there is not as much hardware support (you don't have the floating-point hardware support, since you're operating on multiple integers instead).
The true fallback is that only a fixed quantity of numbers can be finitely represented; those that cannot are forced to a fixed memory-width (say, 32, 64, or 80-bits, for example). Due to this, there is guaranteed an inaccuracy in the storage (forced rounding/truncation) when the number is not finitely represented.
I was taken with the comment "scientists can be fussy"; we need a
nap, I guess?
Seriously, guard bits and high-precision accumulators and addition
algorithms that add the small numbers first (so the roundoff error in the
big numbers doesn't unduly affect the result) are all good ways to treat
roundoff errors. The old VAX/VMS math function libraries were available
with single, double, H_floating, and G_floating just in case you needed
many-digit exponents and really LONG mantissas.
What this article seems to suggest, though, is DECIMAL arithmetic (shades of
COBOL!) as a solution. It is to laugh. Decimal arithmetic manipulation is
familiar from childhood, but has no other virtue. Arrays of 'values' are
containers of variable-length records, you gotta traverse a tree to
find an element (or index tables, or worse, do a linear search); Time
to complete an operation is dependent on the data values. There are
about 70 functions on numbers in the FORTRAN math library; does anyone
want to rewrite them for decimal arithmetic? What kind of precision
'improvement' do you expect in the case of functions like SIN? How
would you even specify a precision goal for such things?
And few if any scientists need more precision than double (there were
those guys in Hans Dehmelt's group, at U. of WA, that did a fourteen-digit
measurement... but they would have got it right even if they had to
use abacuses...)
A more interesting point is on the Fourier transform; there's a theorem
(Parseval's theorem, if you must know) that says a bit of error (noise) added
to a data set will become, after Fourier transforming that data set, the exact
SAME amplitude of noise in the output data. That means that the Fourier
transform doesn't reduce the signal/noise ratio of the input data. I often
have wished that other mathematical and program procedures had the
same property. They don't (and this has been known since Lagrange found
the problem in orbit calculations). And it doesn't matter whether the roundoff
is perfect, because ALL data starts with some noise. And it can never
get better.
Quite simply, Intel no longer uses CISC. Sure, the instruction set is CISC, but it's all microcode reduced to RISC instructions underneath the hood (which was done way back with the Pentium II and may have partially been implemented on the original Pentium). MMX has been dead for a while, replaced by SIMD and SIMD2, which can actually run in parallel to the floating point unit and no longer requires a context switch. Seriously though, outside of the math world, you probably don't need either unless you're doing software rendering of graphics -- the original reason for MMX was to speed up processing of games and video effects in software and this work is now pretty much entirely handled by the GPU.
C'mon, at least Intel is trying. We can't divide 1 by 3 with our base-10 system and our society has yet to crumble. If you want more precision, just use more bits. I'm sure you can figure it out -- after all, you're better than Intel!
And I'm not sure if it can be solved altogether. When you spend a little time meditating over the IEEE 754, you notice a few flaws. The first and most obvious is, of course, that, no matter how precise you want to make it, somewhere there's a cutoff. And, especially when you multiply with floats, that error grows as well. But there's another problem. Two actually.
The first one is the one mentioned in the article, and something everyone who didn't sleep through his IT classes should know: Computers calculate binary, and converting floats from binary to decimal isn't possible without error. There is no way to represent 0.37 in binary, in IEEE754. No matter how many bits you spend on the mantissa. Now, you can argue that, if you make it "big enough", it doesn't matter anymore since it's well within the error margin and when you round it to, say, 5 after decimal, the error vanishes. True. But when you start calculating, when you multiply or, worse, exponentiate, the error grows in big leaps.
Another, less obvious, problem is hidden underneath the way the IEEE754 works: Your error grows as your numbers grow. This might seem obvious, but it is interesting how many people overlook this flaw and problem in everyday life. Since according to the IEEE754 standard, real numbers are stored as exponent and mantissa, if you're dealing with BIG numbers, a fair deal of your mantissa is spent on the "pre-comma" part of your number, so you're losing precision. You can't reliably say that "a double is good for 5 behind dot, no matter what", you have to take into account how many of those precious mantissa bits are spent before you even get to ponder what's left for your precision.
This isn't so much a problem of processors. It's a problem of people understanding how their processors work.
We used to have a Bill of Rights. Now, with the rights gone, all we have left is the bill.
GIMPS looks for Mersenne primes. This is clearly an exact integer operation. However, for speed, they use Fast Fourier Transforms to do the big squaring operation with floating point. Obviously, they need an exact result.
.5, you have the integer answer they need. Note that it's basically impossible to do this without using assembly language, because the order of operations and subexpression elimination definitely matter.
The trick is to carefully calculate exactly how much error each operation can generate. It is possible to know exactly how many bits of your result contain valid information. If you need more accuracy, you can split it into multiple operations. As long as the final accumulated error in their result is less than
Another interesting problem occurs with floating point results. You cannot expect the complete answer to be exactly identical on all machines. Even on the same machine, compiler settings affect the answer: x87 differs significantly from SSE. If you are doing something that needs bitwise identical results on all machines, you need to either implement it with integer math, or do what GIMPS does and do error tracking.
Melissa
"Screw Sun, cross-platform will never work. Let's move on and steal the Java language." - Visual J++ Product Manager
The classic paper is David Goldberg's "Everything a Computer Scientist needs to know about Floating Point", online at http://docs.sun.com/source/806-3568/ncg_goldberg.h tml
One hand raised as requested
I just use integers.
True Story:
.33. .33 is .99.
Business: We need to be able to store thirds, eighths, and hundredths of a unit in the same field. Then we need to add them up, and it has to be exact.
Developer: OK, one second... cool. We'll store the number of 600ths.
Business: 600ths? What is a 600th? Just use 100ths.
Developer: You said you need thirds, right?
Business: Yeah, use
Developer: You said it needs to be exact, right?
Business: Yes.
Developer: 3 *
Business: Oh, yeah. Just round that.
Developer: But that's not exact, and the error can be cumulative.
Business: It's close enough.
Developer: You know, we could store 600ths for accuracy, and display 100ths for user-friendliness. Would that help?
Business: Just use 100ths.
Developer: Right. Thanks. <bangs head on desk>
The field is stored as hundredths.
I know that the problem the article is talking about is the 1.0+1.0=2.000001 problem - but this story is still funny.
Stop-Prism.org: Opt Out of Surveillance
I for one welcome our floating point overlords.
TRHOnline - Staggering Towards Brilliance
If you're interested in rounding (and who isn't?) you might want to read An introduction to different rounding algorithms.
Base-10 is one problem; floating-point is another. If you are certain that base-10 floating point is what you want for financial calculations, use IEE 754r floating-point numbers when it's finalized. But floating point numbers, by design, only maintain a certain number of significant figures. In many financial calculations (say, current bank balances; possibly not long-term stock market estimates), you always want precision down to the nearest cent or tenth of a cent, regardless of how big the number is. That's a job for fixed-point, base-10 arithmetic. (Luckily, libraries for this exist, and IEE 754r also introduces standardized fixed-point base-10 numbers.)
You might be able to get away with floating-point if the mantissa's wide enough for your largest number[*], but why mess around? Fixed-precision arithmetic is easier to understand, so it's the right tool for the job. Save floating-point numbers for the people who need them, who put in the effort to tweak formulas to minimize errors like catastrophic cancellation, and who use them appropriately:
[*] - Maybe; I don't remember all the properties of IEE 754 floating-point numbers off the top of my head, which is exactly my point.
struct fraction { public: long long int numerator; long long int denominator; }; // covers anything in that article
There's a reason some people shouldn't be in industrial computing. Problems like this are trivially easy to solve, and have in fact long since been solved by infinite precision math libraries like GMP. There is a common datatype called BCD (binary coded decimal) which handles these problems by just counting 0..9 in each hex digit and then ignoring the other six values, which solves this at arbitrary precision; the first time I saw that was in Paradox in 1988, but I have references to it in books from the late 1960s.
This is a non-story, documenting one author's infamiliarity with basic practices. Nothing to see here. Move along please.
StoneCypher is Full of BS
Or more importantly, do you math in a system where the level of precision (number of significant digits) is far greater than the answers you require.
That is necessary but not sufficient to prevent the appearance of "weird" results.
Applications that handle money at the retail level, for example, only require three or four decimal places of precision (in the US, at least), so you might think floats are perfectly adequate, but in fact they can produce results that appear incorrect.
Early in my career I worked on a point-of-sale app that had this problem. The previous developer had tried to fix the problem by switching from floats to doubles, but of course that didn't work. Precision wasn't the problem, differing expectations for rounding were. Since changing to a fixed-point representation wasn't possible, I just had to be very careful about making sure that I never rounded early, keeping all possible precision to the end, and then had to write a rounding routine that papered over the discrepancies --not all that hard to do, actually, as long as you have enough precision to start with, and as long as you understand what's going on.
Note to ACs: I usually delete AC replies without reading them. If you want to talk to me, log in.
That's right.. I want to see decimal based computers!
not because it's more efficient but because then I don't have to do stupid binary and hex conversion anymore!
the world should bow to me and my lazy american ideal~!
VLC FOR MAC IS DYING! IF YOU DEVELOP, PLEASE SAVE IT!!
Show of hands: Who did not already understand that floats are approximations?
/.'s readership has really slipped in educational level since the early days. There are a lot of non-coders reading it these days, so yeah, I bet there were a lot who didn't know that...
Sorry to say it, but
HA! I just wasted some of your bandwidth with a frivolous sig!
But floating point numbers, by design, only maintain a certain number of significant figures. In many financial calculations (say, current bank balances; possibly not long-term stock market estimates), you always want precision down to the nearest cent or tenth of a cent, regardless of how big the number is.
In the financial apps I worked on, the mantissa size was never an issue. You have to deal with some very large balances before you start losing stuff off the end of even a 32-bit float's mantissa. I don't think there are any balances in US dollars that would run into trouble with 64-bit doubles. The problems that do arise in financial apps with typical base-2 floating point implementations are caused by the impossibility of precisely representing many base-10 fractions in base 2.
That said, you're right that fixed-point arithmetic is the right thing to use. You still have to worry about overflows, but that's a much less complex problem to manage and avoid.
Note to ACs: I usually delete AC replies without reading them. If you want to talk to me, log in.
the patriot missles in the gulf war woulnt hit there targt in some cases because thier code told them to count time in 1/10 second intervals, which is undefined in base 2 (its a repeting series, 1001001001001...). this lead to them being less acurate after being on for a while
The numerical value in a long and the power of ten in another?
That's just floating point revisited, with 64 bits of significance (less if you mean to interpret the long as binary coded decimal).
Some floating point packages give 64 bits of significance in a long double, although it's not required by the C standard IIRC. But 64 bits only give about 18 or 19 decimal digits of significance, I forget which (but exactly 16 digits if BCD).
Changing the exponent to decimal only makes the range a bit wider. (Waters down the coverage available by not-a-numbers, too, but you probably don't mind that?)
What if the significand (your numerical value) is binary coded decimal? Then you have the advantage that all values map directly to the way we write numbers down by hand. It's a big advantage, because we no longer get surprised by things like 0.2 decimal being stored inexact. But we still have rounding errors when dividing by numbers that are multiples of any primes other than 2 and 5. (And there are lots of those.)
A way to represent repeating fraction strings (such as when you write 0.9 with a bar over the nine to show that it is the result of something like a third times 3) would help for rational numbers. But taking advantage of such a representation is not as easy as one might hope, invoking rounding issues of another sort. (What's the difference between zero point repeating nine and 1.0? How does the computer know when to resolve and how to resolve the cases that aren't as visible?) And you still leave rounding unresolved for irrational numbers such as pi and e and and multiples and fractions thereof.
(Marking the repeating end of a fraction is equivalent to keeping track of numbers as fractions, keeping both the numerator and denominator and only dividing when the result does not lose significance.)
Decimal strings have a very nice advantage, in that the visible surprises are fewer, and if you know you need 16 columns of accuracy, you can calculate the intermediates out to 32 digits of significance. But there are certain nasty surprises that tend to get swept under the rug in decimal arithmetic that binary helps resolve, so it's a kind of pick-your-poison problem, assuming you can choose between decimal strings and binary strings.
And that is really the best we can offer:
Fixed width integers for problems where we know the range doesn't exist the width of the integer.
Fixed point as a variation of fixed-width.
Fixed significance floating point for "easy" fractional problems where rounding is okay.
Arbitrary length numeric (decimal or binary) strings for the rest of the problems, remembering that we still have to deal with rounding.
Maybe sometime we'll figure out how to deal with repeating end elements, and be able to at least keep rational numbers truly accurate.
Some of the irrational numbers might be resolvable by a numbering system based on polynomial series, but I haven't seen much work on generally available libraries for those.
It does what you expect. .1 = .1 with BD. (as opposed to .1000000000000000055511151231257827021181583404541 015625)
2 years and no mod points. Join reddit. Because openness is good.
...somewhere, a calculus teacher just had a heart attack from reading your comment. Pi may have an infinite number of digits in its decimal representation, but that does not make it infinite (rather, since it does not repeat, it is called a transendental(sp?) number).
A mouse is a device used to point to the xterm you want to type in
Many people seem to think of floats as a kind of number that gives fuzzy results; that's b.s. Floating point numbers operate according to precise models. Those models may not fit your calcuations or needs, and one can argue that IEEE has standardized a Rube Goldberg-style floating point model, but none of that makes them inaccurate.
In particular, you can perform bit-accurate integer arithmetic with floating point numbers if you like.
Apparently the author of the article didn't read the stories in RISKS that he cited.
He just stored the causes of the bugs in floats, and they were unfortunately rounded to slightly different causes when he displayed them for the article.
paintball
Well, that explains everything.
Microsoft has a floating point bug in the software that tells us what year their new products will be released...
Now I understand.
Game on!
= Grow a brain...
Do you understand thatis not the same asand thatCan be true?
Every day, many people make the mistake of using floats when wat they really wanted was the ability just to represent large numbers. For example, in Mac OS X, the system uses doubles as representations of time. This is the worst idea I can think of. First of all, floats are imprecise and time is the thing that man can subdivide the most precisely. Secondly, if a Mac OS X machine is on long enough, time will cease to progress becuase of the 2nd statement above!
Plenty of people who thought they knew what they were doing have used floats in places where they are a bad idea. And it continues to today.
So I say no, Computer Science 101 doesn't seem to cover all you need to know about floats.
http://lkml.org/lkml/2005/8/20/95
Since we all know that computers work in discreet values and thus create approximations of select real numbers, why not take advantage of this and create a real number class? Yes, there would be a lot of overloads on the operators and perhaps we have to update the math.h library, but still, this seems to be the most accurate way. Only at display time, or printing does it need to perform some kind of binary conversion so it can be used with some given api, but at least the errors don't get drastically worse with many subsequent computations going against a float. This could be particularly useful in a financial institution where your inputs are gauranteed to be only fractions of 100th (at worse I am assuming). For example, we can implement a class that has two ints such as int numerator, int denominator... and from there we have to overload the operators and maybe create some kind of conversive function as well input/output functions. Well, what do you think? Here is an example... suppose that you have to deposit 33 cents... you would convert and store this into to the realnum obj as 33 num 100 denom. From there I think you can have pretty darn accurate calculations. Oh btw, make sure the user input was loaded as a string and have that parsed into the real num object. Just a thought. I might be wrong though
There are lots of solutions out there. One good compromise in many situations is to store a range rather than a single value; either a min-max pair, or a median value with a precision. Every floating point operation that a computer can do has a predictable limit on the amount of error that it introduces; tracking this amount explicitly alongside your floats and doubles makes an awful lot of sense, and has a relatively small performance cost compared to solutions like decimal arithmetic and symbolic computation.
The article suggests that the approximation error is undefined: for any particular number if could be plus or minus the least precision binary digit. Is that correct? Doesn't the approximation error follow the same rounding rules as everything else, so if the next digit would be a 0 it rounds down but if it would be a 1 it rounds up?
Anyway, this problem is not unique to computers. You can see rounding error in plain decimal math:
1/18 * 18 = 18/18 = 1/1 = 1
1/18 repeats infinitely in decimal, so we choose an arbitary point at which to round, say 4 decimal places.
0.05555(etc) rounds to 0.0556.
0.0556 * 18 = 1.0008, not 1.0000
That seems obvious, so lets try it another way:
(1/18 * 9) + (1/90 * 45) = 9/18 + 45/90 = 45/90 + 45/90 = 90/90 = 1/1 = 1
1/18 = 0.05555(etc) which rounds to 0.0556
1/90 = 0.01111(etc) which rounds to 0.0111
(0.0556 * 9) + (0.0111 * 45) = 0.5004 + 0.4995 = 0.9999 (neither 1.0008 nor 1.0000)
As long as division is the most complex operation, the solution is not to convert the numbers to decimal in the first place. Maintain the number as a fraction until the very end.
Moderating "-1, Disagree" is simple censorship. Have the guts to post your opinion.
Symbolic calculation would be impractical for highly iterated calculations, as you find in many financial and matrix formulae. The symbolic representations would simply become impractically long, and resolving them into actual numbers for presentation to Humans would have exactly the same issues as before.
I once wrote interest-calculation software for a bank. This was new software to replace their old stuff. Naturally, I stored the values in cents, not guilders/dollars/euros, to avoid rounding errors (which really have a big effect in interest calculations).
When I delivered my software, they compared my output to the output their old software produced. There were small differences. They asked me where these came from, and I traced them back to rounding errors in their old software. I showed them this by example, thinking that they would be happy that their new software did not have this problem.
Their response? "The new software should produce exactly the same numbers as the old software." "But the old numbers are WRONG!" "That does not matter, the new software should produce exactly the same numbers as the old software."
It is really hell to make good new software error-compatible with faulty old garbage.
Exactly. The same's true in MS Sql Server, Oracle, or in fact, *any* SQL database. .Net languages actually have a native Decimal type that is guarenteed to have full decimal fideality to six d.p. or something.
Floats are approprate when the value is a truely continuious one that cannot ever be precisely represented in a digital computer system. A classic example would be wave high computation simulations - the "true hight" of a wave being represented could be measured down increasingly better levels -- all the way to the subatomic level, there's no actual 'precisely right' definition. Thus, a float (or a double) is the correct data type. (Or an audio wave file - the actual 'real world' sound pressure is a continious value. CD players just approxmate it with 16 bit integers - and yes, there is a certain quantatisation error with that.)
But in finance, there is a "true" value - my bank account has, for example, two hundred dollars and fifty six cents - it is a completely discrete value. No matter how many times I measure it, it will be exactly the same.
"No, there's nothing you can do about it."
Sure there is, use fractions. For example, 1/3 is exact, whereas 0.3333... is not.
The Maplesoft "Maple" program symbolic math program does this, and only evaluates fractions if an explicit evaluation is called for (eg; by the "evalf()" function).
9/11 Eyewitnesses to Explosive WTC Demolition 1 of 2
Doesn't the word "float" kind of imply that it isn't as accurate as say a regular number? Last time I checked boats didn't have parking brakes.
If you go for fraction of integer you will either have to round them or potentially spend infinite amount of ram.
Think about this, if you multiply a number with a n fractional bits, with a number with n fractional bits.
The end result has 2n fractional bits, or is rounded. Only escape is that if there multiplier gives zero:s in end result. But with lots of calculations you start either rounding things or there will be huge number of bits required to represent the value.
©God
More interesting than cents, when I first started in a commercial DP department, back in the mid-80s, we had a couple of old guys (well, in their 50's) who could remember writing code that had to use the old UK pre-decimal money system (the UK went decimal in 1971). Under that there was 12 pence to the shilling, and 20 shillings to the pound. They similarly converted all values to pence before starting calculations, then converted back to £sd when complete. All on a computer (a Honeywell I think) with less power than my mobile phone.
Floating point arithmetic on computers is not absolutely accurate? Not suitable for
financial solutions?
What next? Sloppy usage of pointers in C may lead to uncanny features?
And I though I knew a thing or two about programming.
1 Earth is warming, 2 It's us, 3 it's royally bad, 4 we need to take action NOW
"But do we ever stop to think what goes on inside that floating point unit and whether we can really trust it?"
That's an ill-conditioned question. Of course we can trust the FPU - to do what it's designed and specified to do. If the programmer doesn't understand how the FPU works, that spells trouble, just like using any other complex machine without proper training.
The question reflects a serious social - not technical - problem that we are facing more and more. Namely, there are so many people who rely on computers but have no idea how they work, many of whom think of a computer as some kind of "brain" or even "god" rather than a complex machine with well-defined capabilities and limitations.
Stories like this recall the old DEC war story about the customer who complained that his VAX was giving wrong answers. It got escalated to galactic support before the customer revealed that his criterion for judging the answers "wrong" was that they differed from those given by his HP pocket calculator! (Never occurred to him that his own calculator could be "wrong", and the whole concept of differing levels of precision seemed to have eluded him).
I am sure that there are many other solipsists out there.
i also only use the DECIMAL datatype in my databases, so i can safely ignore all of this, yet, if i remember correctly, this whole float-thing exists because it is more efficient and machine-friendly. Does anybody have any performance comparisons on large datasets comparing the various number-types, not only in the context of databases? aren't floats supposed to be very FPU-friendly? how are e.g. DECIMALs calculated? would it be better to store dinacial numbers as INT[decimalpoint]INT?
BigDecimal
On solution as you put, is to priority sort your operations.
Another solution, is the Kahan summation algorithm.
Wich, grosso-modo, keeps track of the error at each step, and injects it back at the next.
In your example, in each iteration, the algorithme notice that tha 1.0e1 is missing from the sum and carries it to the next addition. A few iterations later, the carry is big enough to be added to the result.
The advantages are : you don't need to first load all components in a tree, then itteratively sort them and process them all until you're done. In fact you can even use this algorithme in a streaming fashion, were you don't enven need to know how much value will come.
The disadvantages are : some compilers are able to guess that the carry "should mathematically be 0" (actually true in a perfect world with infinite precision numbers) and could "optimise" the code back to a plain normal sum function bypassing the algorithm (and won't subsequently use any other sum-correction algorithm).
"Sufficiently advanced satire is indistinguishable from reality." - [Tips: 1DrYakQDKCQ6y52z6QbnkxHXAocMZJE61o ]
Quantum mechanics on the floating-point stack
This article describes a potential pitfall for visual C 6.0 programmers when using floating point arithmetic. This does not occur with GCC, even on the same platform, because the (int) typecast is sufficiently different.
Why 'Quantum'? The third principle of quantum mechanics is "The act of observing something happening causes a change in the thing being observed." This holds true in the examples given in this article.
The problem stems from the way floating point numbers are handled by the hardware in the Intel-compatible floating point units.
Externally to the floating point unit, floating point values are stored in 32-bit (single) or 64-bit (double) values. However, internally, they are stored in an 80-bit format, as below:
single float: Sign <--8-bit-exponent--> <--23-bit-mantissa-->
double float: Sign <-11-bit-exponent--> <--52-bit-mantissa-->
x87 register: Sign <-15-bit-exponent--> <--64-bit-mantissa-->
Both the single and double precision floats also have an implied leading-1 on the mantissa which is not stored in the actual data, whereas the internal float does not.
The value -4.0 is stored in a double as (hex) 00 00 00 00 00 00 10 C0, when this is written in binary, in the byte order of the diagram above, this works out as
1 10000000001 00000000000000000000000000000000000000000000000000 000000
The exponent is biased, which means that it has a value added to it to provide for negative exponents. In double precision, that bias value is 1023. Expressed in binary, that is 01111111111, so the exponent's real value is 10000000001 - 01111111111 = 00000000010.
The mantissa has an implied leading 1, and the decimal point appears between that leading 1 and the rest of the mantissa, so the value above is negative (the sign bit is set) 1.0000000000... x 200000000010 = -1.0 x 2^2 = -4.0
So far, so good. However the problem lies in functions such as log10(), pow() and so forth that generate floating point results which suffer from accuracy problems. On the intel architecture, these accuracy problems only manifest themselves at the extreme end of the 80-bit floating point format, so for example log10(0.0001) returns -3.99999999999999997e+0000 in the 80-bit format. When this value is stored in a double, via a FST(P) (floating store (and pop)) instruction, the value is rounded to 64-bit accuracy, and results in the bit patten above.
If you copy this value to an integer, you will get the correct result, which is -4.
The error creeps in when you copy the value to an integer directly from the floating point stack, because the value on the floating point stack is still -3.99999999999999997e+0000, and the '=(int)' typecast always chops the decimal places off. The processor converts floating point to integer via a FIST(P) (floating integer store (and pop)) instruction, and the function which the compiler uses to do the cast sets the floating point control word to chop, rather than round, the result. This function, called __ftol is automatically called by the Visual C compiler to do the conversion. It is slow and cumbersome, but it does the job to the specification required. However, you can get different results, depending on when the function is called, because the compiler generates different code depending on how you use floating point results. In all of the following examples, the stack management code has been removed for clarity.
In the instance:
d = log10(0.0001);
i = (int)d;
the microsoft compiler generates the following code:
push 3F1A36E2h ; Push high 32-bits of 0.0001 (double) onto stack
push 0EB1C432Dh ; Push low 32-
There's a system called Binary-coded decimal, which help a binary based system to handle base 10 numbers.
You store each digit of a base 10 number using a 4bit representation. So, in each nibble of a hex reprentation of a number, you get the actual base 10 number.
decimal 1234 = BCD 0x1234.
The advantages are that it is more easy to convert them back from BCD format to decimal to print them. The disadvantage are the increased complexity of circuitry needed to process them in a CPU (and the waste of storage space).
"Sufficiently advanced satire is indistinguishable from reality." - [Tips: 1DrYakQDKCQ6y52z6QbnkxHXAocMZJE61o ]
The newest CPUs/FPUs like Athlon64 work in 64bit precisition (double) already not to mention 128bit registers. And did u guys noticed that on Athlon64 even in 32bit mode the double math is faster then the float math ?
The problem of arbitrary precision for floating point arithmetic has been around for years. A USENIX conference in the early 90's ('90 or '92 I think) had a paper presented that showed a method for testing the precision of your floating point unit, and interestingly enough, only the Motorola worked with acceptable precision. It's been about 15 years since this issue was really addressed (although there was a small reminder in 1998) and I think it's good for us to be reminded periodically that not all hardware is reliable. Or rather, a reminder that hardware is reliable only under specific circumstances. (The original paper made mention of the the fact that the Intel FPU became more unreliable under high heat.) If anyone can point me to the original paper I'd be grateful. I can't seem to find it in my files.
"The mind works quicker than you think!"
Actually, the answer is 42.
PS: That is what part of the alphabet would look like if the letters "Q" and "R" were removed.
The author is a cook. He's making a mountain out of a mole hill, as in anyone who expects write mathematical floating point algorithms using a CPU's FPU should already know of the rounding problems with internal floating point representation. If this matters, and cannot be easily worked around another set of mathematical representations and algorithms should be implemented in software or via use of a pre-existing library.
.37 = 0.37000000476837158203
In any event, here's the 2nd example results on a ppc G3:
66.37500000000000000000 59.00000000000000000000 0.12500000000000000000
result = 59.00000000000000000000
yep, thats rounding error, alright...(I'm bored...) also using 12.5 and dividing by 100, also results in the above #...
From example 1:
BTW: your calculators (TI & HP) will also exhibit this "problem". While I've never used TI calculators extensively, I have used various HP calculators for years, and quickly discovered the rounding on my own before knowing a damned thing about machine representation of floating point numbers and FPUs in general. In any event from extensive use of such machines, I tend to find that the round "errors" tend to cancel each other out in most cases, or that the "error" is of such a small value (billionths or less) of the total that it is negligible in most cases, especially if you limit results to thousandths of a value.
All of this crap being said, there are still some cases where the rounding "error" is evident in results of calculations, and most people are able to spot them and figure out the "more correct" result. If this is not sufficient(and not possible in machine algortithms yet) then the developer as mentioned above SHOULD be writing their own mathematical library or use any one of the 100s of open source or commercial math function libraries that either do not exhibit this "problem" or have worked around them for a particular application.
This entire "article" sounds like someone with half of a clue who got burned...
I hate to troll, but c'mon Slashdot editors -- this is not news. (Shall I, too, write up pages from my first year engineering courses?)
Basically, I agree with you, but as Hamming pointed out in the 1950s you can get yourself into trouble with some thing like:
A = small number, e.g. size of smallest feature in a Celeron-M CPU in microns
B = big number, e.g. distance to Andromeda galaxy in microns
C = (A+B) ... (some set of clever operations) ... - B
The math is fine, but the implementation won't yield the correct answer. because the value of interest got scaled off. That isn't rocket science, but it is suprisingly hard to catch.
That said, Floating Point works suprisingly well for most things. Back in the 1960s, things like 2+2=3.99999 were a fairly common phenomena. Hardly ever happens today. I spent about three decades in the defense industry writing and testing systems that got things from point X to point Y. I think I saw a reasonable selection of the possible errors that folks can make. Other than subtracting big numbers from other big numbers and expecting the result to be precise, I can't recall a single problem with floating point.
If we're looking for something that is basically broken to write an article about, forget floating point. Try event driven software architectures. Or the notion that it is possible to write unambiguous specifications that are also comprehensible.
You can't see ANYTHING from a car, You've got to get out of the goddamned contraption and walk...Edward Abbey
In your first pararaph you recommend that "education" is a good way to avoid gaps in knowledge. I'm sorry, "education" as in "university" education is probably the most efficient way to get gaps in "education."
I've been developing software since the 70s and I have no degree. More than that, I am typically disgusted with those who do. Especially the youn ones who graduate and say things like "why do I need to know that?" A school, inevitably, teaches to a test or some curriculum, where as an inherently curious person will explore more deeply.
I remember reading about floating point math and how it works many years ago, and recall thinking that it was just not suited for many applictions. When writing banking algoiriths, you need to use a precision math package. Double precision, however, is good enough for a lot of calculations as long as you understand that it is not precise.
As for software engineering, I agree with you. We need to engineer more than we do. I have long since been satisfied with the auto mechanic/engineer analogy for software developers. You don't need to be a good mechanic to replace an alternator. You need to be a fairly good mechanic to rebuild an engine. But you want someone who thinks like an engineer to design your engine. Some software jobs are analogus to replacing an alternator, some software jobs, like finance and spacecraft landing probably require engineering skills.
An engineer isn't an education, it is a way of thinking. If you already think like an engineer, a common library or the internet will provide the education you need, probably better than any university.
P.S.
While I do not have a degree, in my 20s I used to help my former high school friends with their course work for their EE and CS degrees. I even disagreed with their professors regularly. I was right, of course, as the professors were teaching from "their books" (often the ones written themselves) and not a plurality of books. One professor yelled at my friend for "not following his teaching." Often times when you "understand" the topic, a more specific and easier solution is obvious. You'd be surprised at how many professors don't actually like students being creative. A creative student is hard to grade because the professors, typically, do not understand the creative appraches and are left with simply looking at correct answers, and the process by which they were arived, is unclear to them. Thus injuring the professors eqo.
Yup, Universities suck because the professors, not all, obviously, but typically anyway, have a self promotional agenda which is not education.
First of all, the best adivce is not to use a non-IEEE compliant floating point language such as Java.
Second, for most finincial transactions, monetary units are generally represented as integers, yes INTs;
long int dollars;
int cents;
this covers the full range of +/- 0-65535 for cents WITHOUT those nasty rounding problems. Most languages have built in currency datatypes, Yes even JAVA. And since it's based on INTEGERS, the poor floating point performance and non-conformance don't come into play.
It sounds like you have spent an inordinate amount of time justifying to yourself why you didn't get your degree. Relax!
You see, this is the problem with computer science today. I am reminded of a story told by CBS' Andy Rooney, he is in some breakfast joint and orders the "fresh squeezed orange juice." When it arrives, Andy tastes it and says to the waiter, "This is not fresh squeezed orange juice." To which the waiter replies: "Yes, it is, let me get the bottle and show you."
Yes, IEEE floating point is a very well documented standard. Absolutely, it is a very well documented precise model for approximating numbers.
Anyone who whishes to argue otherwise must understand that the static representation of a number must have sufficient data with which to represent it. 64 bits is not enough data to accuratly represent the range of data it is supposed to. Now, double precision has enough precision for calculations where there is a measurable percent of inaccuracy in the numbers, i.e. like electrical circuits and near range rocket trajectory, but when it comes to money, no.
You can improve the situation as some FPU systems have 80 bits internally, and some compiler switches to preserve the precision in the FPU, but if you are doing banking, you have to use a package like BCD math.
I am very small, utmostly microscopic.
It sounds like you have spent an inordinate amount of time justifying to yourself why you didn't get your degree.
It isn't a justification so much as it is a disgust with computer science trends. I don't know a single person in my age/experience range that thinks CS grads are qualified or up to the task of doing anything more than "business logic" crap. The CS grads today do not understand computers or computing. They do not understand how the machines really work. Thus, if you want to hire someone to write a device driver, graphics routines, high speed math, or any non-trivial application, you can't look for a young guy. What's even worse, is that the CS guys are told that the actual computer is unimportant and are poisoned by the nonsensical Djykstra quote they are fond of spouting.
There are "real" issues with "real" computers, and this math article is just one example. "real" computers can't do anything but simple arithmatic (add/sub[mul,[div]]). FPU's implement more but as numeric approximations that are generally "close enough," but are too often confused for accurate math. Implementing real word concepts on computers efficiently is a real science. Implementing real world concepts on a theoretical computer is nonsense.
e.g., money values...
How they ended up in financial software is a worry... then again there's a lot of SHIT software out there...
I run: Windows, OS X, Linux, FreeBSD. Just because you have a hammer, doesn't mean everything is a nail.
You're half right. An engineer isn't a degree. A degree's not a worthless piece of paper, though, and, although you might not get much value from a college education (good grief. Were your friends students at a community college?) from one, they're still very useful. At the very least, there are better schools out there.
Canthros
Fixed point isn't really necessary either.
If you do calculations using 32-bit integers representing (cents/tenths/hundreths of cents) it works out quite well.
I mean, do you need a cash register than can tally sums > $1000000?
THIS THING CAN TURN ON A DIME, MACROSSZERO STYLE ALSO FUCK BETA, ~NYORON
"Can you explain this charge of arctan(gamma(1/cube-root(17)) on my account?"
Floating point numbers are not approximations. Putting aside NaN and inifinity, every bit pattern represents a specific rational number. The relevant standards define the basic operators (addition, subtraction, multiplication, division and square root) as returning the floating point number closest in value to the ideal result. It turns out that this guarantee is quite cheap to implement in hardware.
...0000000000 but with a binary notiation only rationals where the denominator is a power of 2 can reduce in this way.
:) It's not like these problems magically disappear if you use a better math library or the financial industry can avoid using e from time to time.
The next thing to understand is that the representation represents fractions in base-2 instead of base-10. For us 0.3079 means 3/10 + 0/100 + 7/1000 + 9/10000. For the computer 0.1010 means
1/2 + 0/4 + 1/8 + 0/16. In our notation rationals with a denominator that is a multiple only of 2 and 5 eventually reduce
Originally computers were made using base 2, base 10 and base 16. Eventually someone proved that base-2 always gives more significant digits per bit than any other representation and the other floating point formats basically disappeared.
Now, at first glance this may seem terrible -- but it almost never really matters. In a base 10 scientific system you'll almost never be able to operate solely inside the rationals that are represented exactly in decimal fractions. Even common financial calculations (such as amortizing a mortgage) use irrationals and applying percentages to arbitrary amounts of money obviously results in fractional pennies
To sum up, read up on floating point. It's a very elegant, well thought-out systems designed for scientific computing but with general utility. If you understand it you can use it. And if the text you are reading describes the numbers as approximations stop reading and look for a better text.
A quick Google, oops I mean a quick search using the web site www.google.com, on the Vancouver Stock Exchange turned up this.
I still remember the time the prof in our numies class talked about rounding down if the trailing digit was 1-4, rounding up if it was 6-9, and randomly choosing up or down if it was 5. We were all thinking...Wha? None of the packages I have used since then (eg NASTRAN) employ such a strategy as far as I know, although it may be buried deep inside the guts somewhere.
But it's always been in the back of my mind, doesn't rounding up on 5 introduce a bias?
Equine Mammals Are Considerably Smaller
Floats have their uses, but generally they trade exactness for range. And huge pifalls for the uninitiated, like comparing floats for equality.
AFAIK, accounting systems are still done in COBOL-heretige BCD fixed point math, usually as integer mils (one thousandth of a cent). Spreadsheets run into trouble because they are usually double floats.
They are useful for storing decimal quantites unambigously in databases and flat files.
However they are not as useful for code that manipulates them heavily:
* MP libraries that use full-on binary representation are always faster and more memory efficient unless we're talking about an IBM mainframe
* It's a pain to up and downconvert from "normal" datatypes
In-memory representations are probably better served by 64-bit quantites of fractions of a currency unit or a fixed point type. (Using an MP library to simulate BCD is overkill since a 64-bit integer has a greater mantissa than any financial system will ever need, even if calculating the National Debt to the penny)
On 32-bit systems that lack instructions like MMX/SSE/Altivec to handle 64-bit quantites, one might instead use a packed struct of two 32-bit quantites at appropriate currency divisions (US: dollars and ten thousandths of cents, JP: thousands and hundreths of Yen) can also work. The second method is more cumbersome but there are some nice tricks: like when summing you can get away with resolving the carry until outside of the loop as long as N < 1000 or so.
In any case packed structs are probably unnecessary on 32-bit architectures anymore because most compilers and scripting languages have a decent 64-bit emulation mode that is as good as any library implementation.
THIS THING CAN TURN ON A DIME, MACROSSZERO STYLE ALSO FUCK BETA, ~NYORON
We all know that the answer to this problem is to represent numbers as non-approximate values.
If you have a fixed number of decimals, just including a point in an integer will save storage space: 12345 = 123.45
Alternately, store as strings (though accept 8 bits per character, including decimal) and use string math, such as bcmath. This of course at the expense of speed.
You will maintain perfect precision in these cases.
The FPU uses exponents and anyone with the basics of programming knows this. Now we all know why you "don't let your 12 year old niece" make your crucial purchasing software or online store as is all too common- they ignore these facts and feel that double and single are good types... until you fail to balance at the end of the year.
-M
when you see the word 'Linux', drink!
Multiplication is equivalent to a convolution of two discrete arrays.
It's a O(N^2) operation if done using the multiply, shift, add method.
An FFT (of which there are integer variations) is a O(N*log(N)) manipulation of the data.
When you transform both arrays, you do a straight component multiply, then you untransform the result.
3 * O(N log N) + O(N) O(N ^ 2) for very large multiplicands.
We're talking about way outside of the range of most scientific or financial applications. It's an important speedup for mathematical research and certain kinds of statistical analysis.
THIS THING CAN TURN ON A DIME, MACROSSZERO STYLE ALSO FUCK BETA, ~NYORON
It's a classic problem. Back in the first Gulf war, the ground based defense missiles (I think it was the Patriot line) had to keep being rebooted every couple of hours because their guidance systems had a cumulative numerical instability in them. It was the first time they had run the missiles on continuous hot standby for periods of days at a time, so it was the first time that the problem cropped up. Talk about learning the hard way. Being able to analyse an algorithm for its numerical stability should be part of every programmer's arsenal of tricks.
Okay, Show of hands: Who did not already understand that floats are approximations? Anyone? I didn't think so. I've gotta wonder why this story ever made it into Slashdot. This is more worthy of Time magazine where it can be spun as a startling new revelation into the dirtier corners of computer science and foisting a lie on the public.
LOADS of people don't understand it. And I MEAN people with CS degrees.
Mostly I've worked in scientific areas. I've given the "here's what's really going on inside floats" dozens of times. Most of the techically oriented types said things like "Oh yeah, I remember, floats aren't exact".
I've worked for a while in a billing company. Most of the programmer types didn't have a clue about floats. But then, most of the meat-code in that area was setup by someone who did, and was not touchable.
/F
Stupidity... has a habit of getting its way.
A while ago I was going through a text on Astronomical Algorithms.
The beginning part of the book had a "be careful about computer calculations" section for those not already familiar with the concept.
One of the samples showed a simple program (in BASIC, of course!) which determined the number of significant digits used on your particular environment.
I forget the exact procedure the book used, but it involved doubling a number within a loop and then terminating the loop when the expression "x == x + 1" was true. (i.e. when adding one to a number did not affect the significant digits.)
New to Lisp, I decided to produce a Lisp version.
... To my surprise, the program ran for several minutes on my sooper dooper pentium 4 machine without terminating.
It turns out that in my naive, straight forward implementation, I was implicitly using Lisps 'bignum' support. It seems that you "automatically" get "bignums" within Lisp unless you specifically ask for something else.
A second snippet of code within this section of the same book showed how repeated rounding errors can accumulate to throw off an answer. For this, they repeatedly summed the following calculation "x = x + (((x+1)/3)*3)-1" IIRC. (The answer should always be "x".)
They showed example results from various machines for several iterations. The results dramatically illustrated the accumulated error after even a few iterations.
... Except for my naive Lisp version. It also seems that Lisp gives you a fractional datatype by default! The default implementation produced the exact answer.
Minor things really, but this was my first experience with a computer language that fit what I had learned in math class and I found it some what refreshing.
As a CS professor, I agree with much of what you say.
There are certainly lots of CS professors out there who don't know much about CS and who teach (essentially) from ideology.
But the problems go deep. Part is the expectations of students who believe that they are purchasing an education and are therefore entitled to get good grades. Part is the way many modern universities work where "retention" is king and therefore we must keep students in the program or the program dies. Even if that means that students stay in programs that they should not be in. Part is the trend toward codifying "outcomes and assessments" in courses, which usually means not just "objective tests", but objective tests that cannot vary much, even over the course of years. As an example, in one program I know of, the person teaching the "CS 1" type courses has no real world experience and does not teach any kind of problem solving, but the professors who do have the background are not allowed to teach the CS 1 courses, because they'd scare off the students - and we're back to retention.
Got any suggestions?
Everyone knows about rounding problems with floats. What people don't seem to realize (and this goes for many real "Rocket Scientists" I've known) is that a float only gives you a fixed amount of digits - that's all. You can have a highly precise small number or a really big number. You cannot ever have a precise, big number. It just so happens that these same "Rocket Scientists" like to represent time as a floating point based on some 1970 epoch. Guess how accurate that is going to be in a couple of years. How do they solve this problem? The "double double" type of course!
Why would this count as "news". Everyone who has to deal with this would already know about it.
OK, I can't contain myself. OK, take the cost of the education, specifically CS or programming, and the cost of the loan, and the time spent in the university vs working getting real experience, and you'll see that going to the university is less cost effective. So, you're right, it isn't worthless, it is less than worthless. My advice to *anyone* wishing to get into computer software development is to teach yourself how to program and focus on MBA studies, because business skills are now vital in the industry.
Oh, by the way, the school's were Northeastern University, UMass Amherst, and Bridewater state. The school that had the worst professors was Northeastern.
If you can represent a number by an inner and outer bound, and then every time you perform a calculation using that number, you expand the bounds to represent the margin of error, you get a nice way of always knowing your precision.
So take the real value, 1/3, and represent it as say, [0.33333329, 0.33333334].
After a few operations, you could end up with [4.2134243, 4.2136963] as an answer. This tells you that your answer definitely lies in the range above, and that you have lost some certainty of the location of that "real value answer".
There's some more info here on a project website http://shrinc.ca/?n=237&h=1&r=286&wc=1
Business skills could also help you, buddy. If something is worth $10 and you pay $20 for it, that does not mean it's net worth is -$10. That seems to be what you are saying, with your pithy "less than worthless" comment. Ironic, when we're branching off a topic about accuracy in financial programs. You have the float thing down, but either you are a dolt when it comes to other financial matters, or, more likely, you are shrewdly equivocating and bending the truth to serve your purposes.
The question of whether education is worth more than the opportunity cost of money in the bank + potential practical experience is stickier. Which is precisely why my hackles are rising from your posts, which clearly posit that there is an absolute answer to that question, and the answer is no degree.
People use floats because they can hold "really big numbers". But they don't really hold the really big numbers, they just approximate them.
Floats are imprecise. They appear precise in ranges of represented values and for sizes of errors that people commonly use. But in actuality, they will silently use an approximation of the number you tried to put in instead of the real number if the number cannot be precisely represented.
That's why they are imprecise, and that's one of the big dangers.
http://lkml.org/lkml/2005/8/20/95
dealing with some data that can't be measured correctly anyway, like weight, hight, etc. "Continuous values", that is (vs descrete).
You guys actualy program? i though this was /.
whats happened to cpan, cut and paste and modules?
You start with an insult, ad hominem, you lose one point.
Yes the pithy comment was somewhat simplistic, but it wasn't any sort of logical cop out either. The number speak for themselves. There is a conventional wisdom that it is valuable, but "conventional wisdom" is often counter to facts.
It is like the argument of buying a house vs a renting an apartment. It is not a given that one is better than the other. If you can find an apartment in which you are happy living at a substantally lower rent than you would pay for a mortgage, if you had financial self control, you could easily save more than you would be building in equity minus what you pay in interest.
If a university education is not required for your career, and in software it is not, then you have to measure the cost/benefit of the education. A CS degree fails the cost benefit test, especially since it does not actually prepare you properly for your field. You STILL need experiece. Since the knowledge one obtains from the school is readily available freely at the library or internet, and is more up to date, then the school add no value for a dedicated person. The time you spend at the school actually takes experience time away from your career.
Like I said in another thread, get an MBA with some basic programming. Learn the rest yourself. You will do far better than a McCS grad.
because I got my doctorate by writing algorithms that chose analytic and numeric method based upon the representational accuracy of floating point arithmetic when doing differences between very similar large number.
me.
IEEE 754 includes a "double-extended" format, whose size must be at least 79 bits -- it's allowed to be longer -- and which is, in almost every implementation, 80 bits. Who knows what the parent AC is thinking.
-Tom Duff
I have an open task right now that requires me to prepend a zero when parsing vendor data that has only four digits.
501 Not Implemented
Actually, the base doesn't matter for fixed point arithmetic. We used to use 48 bit integers: struct money { long hi; unsigned short lo; } This is particularly efficient at add,sub,mul,div even when translated from C by a relatively dumb compiler. and 48 bits is enough for the national budget of the US tracked in Lira. Important for a 16Mhz 68010. But nowadays, we just use the 64-bit integer type built in to all C compilers and Java. Plenty fast enough on a modern 32-bit processor.
The tricky programming issue is keeping track of which variable has what implicit fixed point and make sure they don't overflow. In C++, we have a template FNUM type where the int parameter is digits after the decimal point. But if you are careful, this isn't really necessary - and in fact doesn't help all that much. A comment giving precision by each struct money variable or database field is just as good.
Finally, someone said it! It bugs me to no end how programmers call themselves "Software Engineers" when every other kind of engineer (except maybe the guys that drive the trains) had to take a test and work under a licensed engineer for a certain period of time before assuming the title.
See Numerical Robustness for Geometric Calculations (aka EPSILON is NOT 0.00001!) from GDC 2005 http://realtimecollisiondetection.net/pubs/
The patriot is a mobile surface to air missile system. It was designed to shoot down aircraft over europe during ww3.
It was discovered that the missile was accurate enough to potentially be able to hit a ballistic missile, upgrades to the system were put into place to give it the capability.
The gulf war came around, and the patriots got their trial by fire. It was the first time a hostile ballistic missile was shot down. Really quite a feat to pull off outside of a planned test.
It also proved serious flaws. However such flaws are to be expected with you put any new piece of equipment into a war. A major one besides the one you mention(and a much more dangerous one) is the patriot's warhead. Being that it's a SAM, it's warhead is designed to remove the target from the air, not to obliterate it. When you're shooting at an aircraft, that's the entire goal. When you're shooting at a scud which is barely being aimed as it is, all you're doing much of the time is changing the course of the warhead.
Still, Non-perfection is a long way from dismal failure, especially when you're combat testing something that's never been tried before.
Yes, IEEE floating point is a very well documented standard. Absolutely, it is a very well documented precise model for approximating numbers.
Floating point numbers are no more and no less "approximations" than integers or BCD numbers: for some operations and pairs of arguments, they give you exact results, for some, they give you rounded or truncated results, and for some, they give you overflow/underflow.
The rules are a bit more complicated for floating point numbers than for integers (e.g., for integers, only division truncates), but there is nothing intrinsically "approximate" about them. You can choose to view floating point numbers as approximations in your application but many people also use them for exact computations.
Sorry, but you clearly have no idea of what you are talking about. A floating point number can not 100% accurately represent every number within its range. Given any specific number, one can predict the exact representation, sure. When a series of calculation are performed one can not be sure of th outcome, exactly. For instance, if you have an array of numbers with a wide range of values, you will want to add in the order of smaller to larger. If you do it larger to smaller, you may get a different result. That is *NOT* exact by any definition.
Floating point is an inexact math system, it is design for speed, not accuracy.
Well, you're more right than most who have posted here. Several "real programmers" here seem to think that BCD eliminates cumulative errors. Fixed-point is not completely moronic, but you still need extra decimal places sufficient to handle iterated computations such as: interest calculations with rates to five significant digits compounded over decades, subtractions of nearly equal quantities, multiplications by one+/-epsilon or near-inverses, and so forth. But you misspoke about fixed-point numbers having fixed precision - rather, they have fixed accuracy. The former depends on the number of distinct values that can be represented, the latter depends on the absolute size of the smallest representable unit. Any given fixed-point representation has a different effective precision for every different numerical value it can hold, while floating-point numbers have a different minimum distinguishable increment (accuracy) for each value of exponent. As others have pointed out, IEEE-754 floating-point numbers have known accuracy and proper mathematical behavior, but they occasionally require some skill to use. So do the fixed-point systems, but they have less robust error behavior than the IEEE numbers with their curious special cases and ranges. Given sufficient bits in the floating-point number, the accuracy is as good or better than needed for any type of financial math (better really- finance often isn't as precise as most people here seem to think, and almost never so accurate). If you think that accuracy is important in this kind of application, though, why object to a couple of extra bytes per number? But really it's the fixed-point that wastes bits on the seldom-used but always-allocated headroom needed to store large values.
The Intel 80-bit double-extended precision floating-point number format has 64 bits of mantissa, and can exactly represent any integer between -2^64 and 2^64. Using only the positive range, that is over 19 decimal places, more than the 10 digits before and 8 after the decimal point which another poster has said is the numerical accuracy required of banks in order to be allowed connection to the London markets. In most cases, the 80-bit floating-point number is far more accurate: for account balances between +/- 16.7E6 currency units, the accuracy will be accurate to within about +/- 2^-40 units (12 decimal places), and for balances within +/- 8.6E9 currency units the accuracy will be within about +/- 2^-31 units (9 decimal places + 1 bit). Between about 137 - 274 billion-unit accounts one would have to make do with only 7.8 decimal places of accuracy instead of 8, but there would still be over 6 decimal places of accuracy even for single accounts of up to 17.6E12. So floating-point numbers can indeed guarantee high accuracy; for ordinary currency numbers, floating point has higher accuracy than almost all fixed point implementations. (And even if you do crowd the limits, the underflow is gradual due to the "subnormal" and "denormal" numbers which are smaller than the normal range.)
Examples:
If you were to add fractional-cent amounts calculated to have the maximum possible error of representation in 80-bit format (7.45E-7 cents ) to a billion-dollar account once per minute for fifteen months, the accumulated error would still be less than half a cent. In more normal acccounts of 1 million dollars, the 2.27E-13 cent maximum error would have to be added once per millisecond for nearly 70 years to reach half a cent accumulated error. Any error from adding approximated binary fractions (1/odd number, etc.) would of course usually be less than the maximum error.
Floats are usually much more convenient than fixed representations for practical higher financial calculations. However, if one needs to do something less useful - say, calculate the interest on the US national debt compounded and recalulated each microsecond in units of quadrillionths of Weimar-era hyperinflated Marks, (and you are too 1337 to use a 128-bit format), then use arbitrary-precision arithme
"Is life so dear, or peace so sweet, as to be purchased at the price of chains and slavery?" - Patrick Henry
You could just discard decimal numbers altogether and only use integers. After all, it's the enterprise-y thing to do.
...I'm not interested.
Old news.
Have you read my journal today?
The Daily Telegraph (London UK) reports that the US Bureau of Labor Statistics has a rounding problem.
m oney/2006/08/15/cnus15.xml
http://www.telegraph.co.uk/money/main.jhtml?xml=/
It seems that doubtful rounding practices have distorted US consumer price index figures.
Acton, Forman, Real Computing Made Real, Princton Univeristy Press.
This humorous, informative book will chasten and remind the casual user of floating point numbers! The losss of significant digits can be truly tragic....
Numerics course I,
exercise sheet 1,
1 a) Proove that floating point addition is not assoiative
Floats are imprecise.
You can do this statement:
x = (float) 16777215
And it sill compile, run and happen. The number will appear to fit.
Except x doesn't hold precisely 16777215. It holds approximately 16777215. Yes, everyone should know that things like this can occur and program so they don't run into such problems. But the whole point of the article is people don't know this, and they don't program around such problems.
For example, double-precision reals can exactly represent all integers up to 2^53, and all even integers up to 2^54, and all integers divisible by four up to 2^55, etc.
They can accurately represent cash values in pennies up to 8 trillion dollars (or 8 billion, if you want to count thousandths of a cent).
These statements are completely true. They also lose close to non-obvious problems like that even though it can exactly represent all integers up to 2^53, if the proper result for the formula you are computing is an integer up to 2^53, it doesn't mean the double that represents that result will equal that integer. Often it will be close to that integer within some error bars. You really should compute these error bars so you can then compare against the proper result or do a round to decimal place (in this case integer, the 0th decimal place) within these error bars against that value. But instead people do
if (81 == x)
and it doesn't match.
The IEEE standard does a great job with guard bits to attempt to prevent this, but in the end, it is up to the programmer to understand that precision will be lost (because floats are imprecise) and how to work around this.
Ask a programmer if they know floats are imprecise and they'll say they are and they are familiar with the issues. Then ask them if 0.1 can be accurately represented in a float and they'll look at you quizicaly as if the question were to trivial that it doesn't even need to be asked. When you point out it cannot, they'll maybe say something like "not my problem, I use doubles instead of floats anyway, they are more accurate".
It's a big problem. Floats are imprecise, they approximate values in situations people people don't expect. And because of that, at the end of a sequence of operations, they often end up with a messy 0.000000001 sticking on their "precise" integer less than 2^53 and they rarely investigate the proper way to handle it.
http://lkml.org/lkml/2005/8/20/95
A dual system? You know, where you do single-cycle mul/div in one "LNS half" of the register and then, in another number of cycles, on background, you update the other "float half". OR you do single-cycle add/sub in the "float half" and update the "LNS half" on the background.
It's better to be the foot on the boot than the face on the pavement. ~~ tkx Kadin2048
A floating point number can not 100% accurately represent every number within its range.
Neither can an integer variable; integer variables only represent integers within their range. Floating point numbers can do that, too, and a lot more.
When a series of calculation are performed one can not be sure of th outcome, exactly.
Of course, one can, just like with integers.
For instance, if you have an array of numbers with a wide range of values, you will want to add in the order of smaller to larger. If you do it larger to smaller, you may get a different result. That is *NOT* exact by any definition.
Neither integers nor floating point numbers obey associativity.
Floating point is an inexact math system, it is design for speed, not accuracy.
Bullshit.
I read an article in (I think) Dr Dobbs about this sort of stuff, describing a scheme using factorial base arithmetic, which was able to represent any rational number in finite space, with a reasonable constant. The gist of it was that instead of each successive place representing some quantity divided by a higher power of the base, it represents a quantity divided by a larger factorial.
The upshot of it was that as long as you restrict yourself to rational numbers at the start, and perform only +, -, * and / operations (steering clear of roots and powers with non-integral exponents, for example) you will be able to get an exact result. Depending on how many calculations you go through and what numbers you generate, the representations might grow quite large, but they'll always be exact.
One might observe that the first terms are necessarily small and there is wasted space and time, but a refinement of the technique could lump terms together to conserve space and speed up processing.
That's the idea anyhow, and it appealed to me but I've seen little or nothing of the technique since that article was published.
Regards.