You've probably seen this old chestnut by now.
Insert your own joke here. Google can't be wrong -- math is! But Google is hardly alone; this is just another example in a long and storied history of obscure little computer math errors that go way back, such as this bug report from Windows 3.0.
On my virtual machine, 12.52 - 12.51 on Ye Olde Windows Calculator indeed results in 0.00.
And then there was the famous Excel bug.
If you have Excel 2007 installed, try this: Multiply 850 by 77.1 in Excel.One way to do this is to type "=850*77.1" (without the quotes) into a cell. The correct answer is 65,535. However, Excel 2007 displays a result of 100,000.
At this point, you might be a little perplexed, as computers are supposed to be pretty good at this math stuff. What gives? How is it possible to produce such blatantly incorrect results from seemingly trivial calculations? Should we even be trusting our computers to do math at all?
Well, numbers are harder to represent on computers than you might think:
A standard floating point number has roughly 16 decimal places of precision and a maximum value on the order of 10308, a 1 followed by 308 zeros. (According to IEEE standard 754, the typical floating point implementation.)Sixteen decimal places is a lot. Hardly any measured quantity is known to anywhere near that much precision. For example, the constant in Newton's Law of Gravity is only known to four significant figures. The charge of an electron is known to 11 significant figures, much more precision than Newton's gravitational constant, but still less than a floating point number. So when are 16 figures not enough? One problem area is subtraction. The other elementary operations -- addition, multiplication, division -- are very accurate. As long as you don't overflow or underflow, these operations often produce results that are correct to the last bit. But subtraction can be anywhere from exact to completely inaccurate. If two numbers agree to n figures, you can lose up to n figures of precision in their subtraction. This problem can show up unexpectedly in the middle of other calculations.
Number precision is a funny thing; did you know that an infinitely repeating sequence of 0.999.. is equal to one?
In mathematics, the repeating decimal 0.999Ö denotes a real number equal to one. In other words: the notations 0.999Ö and 1 actually represent the same real number.
![]()
This equality has long been accepted by professional mathematicians and taught in textbooks. Proofs have been formulated with varying degrees of mathematical rigour, taking into account preferred development of the real numbers, background assumptions, historical context, and target audience.
Computers are awesome, yes, but they aren't infinite.. yet. So any prospects of storing any infinitely repeating number on them are dim at best. The best we can do is work with approximations at varying levels of precision that are "good enough", where "good enough" depends on what you're doing, and how you're doing it. And it's complicated to get right.
Which brings me to What Every Computer Scientist Should Know About Floating-Point Arithmetic.
Squeezing infinitely many real numbers into a finite number of bits requires an approximate representation. Although there are infinitely many integers, in most programs the result of integer computations can be stored in 32 bits. In contrast, given any fixed number of bits, most calculations with real numbers will produce quantities that cannot be exactly represented using that many bits. Therefore the result of a floating-point calculation must often be rounded in order to fit back into its finite representation. This rounding error is the characteristic feature of floating-point computation.
What do the Google, Windows, and Excel (pdf) math errors have in common? They're all related to number precision approximation issues. Google doesn't think it's important enough to fix. They're probably right. But some mathematical rounding errors can be a bit more serious.
Interestingly, the launch failure of the Ariane 5 rocket, which exploded 37 seconds after liftoff on June 4, 1996, occurred because of a software error that resulted from converting a 64-bit floating point number to a 16-bit integer. The value of the floating point number happened to be larger than could be represented by a 16-bit integer. The overflow wasn't handled properly, and in response, the computer cleared its memory. The memory dump was interpreted by the rocket as instructions to its rocket nozzles, and an explosion resulted.
I'm starting to believe that it's not the computers that suck at math, but the people programming those computers. I know I'm living proof of that.
$ python
Python 2.5.2 (r252:60911, Sep 20 2008, 22:32:52)
[GCC 4.2.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> 399999999999999-399999999999998
1
>>>
Python WIN!!!!
thebigh on May 13, 2009 10:09 PMReminds me of the Pentium Floating Point Division Bug:
http://www.cs.niu.edu/other/pentium.html
There are languages that handle arithmetics well.
I known two examples (I am sure, there are more of them)
Python: has built-in infinite precision integer numbers
Lisp: has built-in infinite precision integer and rational numbers and has arithmetical operations defined same way as in math (e.g., (mod -1 10) = 9, not -1).
So, it is clearly solved problem, not sure why not all language designers use infinite precision integers and rationals.
"In mathematics, the repeating decimal 0.999Ö denotes a real number equal to one.", and "This equality has long been accepted by professional mathematicians and taught in textbooks."
Not the textbooks I read (or did when I was in university - it's not a favorite pasttime of mine...). The correct mathematical explanation is that 0.99999... (zero point nine recurring) approaches 1. Any pure mathematician (probably not many read Coding Horror...) would surely agree.
Good post, though!
Darren on May 13, 2009 10:47 PMPHP also calculates the example perfectly.
Jan Hancic on May 13, 2009 10:50 PMIn case it hasn't bit you yet, you might be surprised that a nice large, simple decimal like 0.1 is an infinitely repeating value in binary: .0001100110011...
You have to be very careful doing floating point math[1]. Especially when it comes to testing for equality[2].
[2] http://stackoverflow.com/search?q=floating+point+equality
Dennis on May 13, 2009 10:53 PM@dmitry_vk
Yes, several languages do support infinite precision - assuming infinite memory, of course. But they're usually slower than using the standard 32-bit or 64-bit types that are fundamental to the machine architecture, because they're having to do a lot of the calculations in software, instead of hardware. It's one of those tradeoffs we keep running into...
Here we go again (thanks, Jeff, for re-opening a can of worms).
@Darren: Nope, sorry, 0.999... EQUALS EXACTLY 1.0 no ifs ands or buts. Read the Wikipedia article. It includes some very straightforward proofs.
Dennis on May 13, 2009 10:56 PMNot to mention that typical floating-point numbers can't represent some decimal values accurately. Some programming languages, including C#, have a decimal type that's floating-point but works in base 10 instead of base 2.
Mr.'; Drop Database -- on May 13, 2009 10:58 PMThe article is a bit misleading (to me, at least). I understand the sentence "A standard floating point number has roughly 16 decimal places of precision" as "If you have a real number with about 16 decimal places, floating points can represent it accurately", which isn't true.
A trivial example of this is the decimal number 0.2, which can never be accurately described with IEEE-754, because the ".2" is represented with an infinitely repeating pattern of "1001" ("100110011001...").
Henrik Paul on May 13, 2009 11:00 PM"Interestingly, the launch failure of the Ariane 5 rocket, which exploded 37 seconds after liftoff on June 4, 1996, occurred because of a software error that resulted from converting a 64-bit floating point number to a 16-bit integer."
I'm tired of reading such nonsense. That's a total misunderstanding of the reasons that led to the loss of the rocket.
Reusing Ariane-4 software in the larger Ariane-5 (with different constraints) can hardly be called "rounding error".
Vinzent Hoefler on May 13, 2009 11:06 PMPutting the Excel 850*77.1 bug in there is a little misleading as Excel does in fact calculate the result correctly. The display logic was broken on assembler level which isn't exactly Excel doing a wrong calculation, but rather a programmer's oversight.
It's not an artifact of how computers handle numbers in contrast to the other examples you give.
Johannes on May 13, 2009 11:06 PMOh no. Yet another place infected with the 0.(9) vs 1.0 debate!
IMil on May 13, 2009 11:08 PM@Simon: python and lisp implementations handle "short" number ("fixnums", as they are called in lisp) with the same speed as arithmetics machine words (e.g., as in C). And long arithmetics is only used when numbers do not fit into registers anymore. So, you can see, that on "short" numbers, it does not make difference, but on "long" numbers, correct but slightly longer operation is preferred to fast but incorrect.
@Dennis:
nobody forces to represent 0.1 as a binary fraction. 0.1 is a rational number and is usually should be treated as such (e.g., when precision is required).
simple decimal like 0.1 is an infinitely repeating value in binary:
Actually, the Excel bug was from an incorrect 16-bit to 32-bit assembly translation resulting in a bad branch, not an approximation issue.
Most of the "calculator" bugs are because calculators should be using decimal (or whatever base they are in) arithmetic. Of course, that is way more work to write...
@dmitry_vk: Most languages don't support bignum because of the code bloat inherent. C++ will likely compile these statements like:
int a = 1, b = 2, c = a + b;
=>
mov [a], 1;
mov [b], 2;
mov eax, [a];
mov ebx, [b];
add eax, ebx;
mov [c], eax;
bignum a = 1, b = 2, c = a + b;
=> (roughly)
push 1;
lea ecx, [a];
call [bignum::bignum(int)]; # init a with 1
add esp, 4;
push 2;
lea ecx, [b];
call [bignum::bignum(int)]; # init b with 2
add esp, 4;
lea eax, [a];
push eax;
lea eax, [b];
push eax;
call [operator+(bignum const&,bignum const&)]; # add a, b
add esp, 8;
mov [$temp], eax
push eax;
lea ecx, [c];
call [bignum::bignum(bignum const&)]; # init c with copy of temp result
add esp, 4;
mov ecx, [$temp];
call [bignum::~bignum()]; # delete temp result
add esp, 4;
And of course, there is also the implementation of those bignum:: operators. If your implementation is pretty clever, you should be able to inline the int initializations, but the addition temporary and it's copy and delete you won't (without some unlikely flow-analysis), because the implementations will have to account for memory allocation. There are some pretty serious benefits to using value types over reference types.
Python, Lisp and Haskell get it partially because they are already pretty slow, so the bloat doesn't hurt in most cases and partially because (at least in Python and most Lisp cases) they will be using bytecode anyway.
@Darren
I am a mathematician, there is no difference between .9(bar) and 1. Just because we can't count to infinity doesn't mean that it doesn't exist. At infinity, it is equal to 1. As Dennis said, see the wikipedia page on it for proofs.
http://en.wikipedia.org/wiki/0.999...
@Simon Buchan: "Python, Lisp and Haskell get it partially because they are already pretty slow"
"Lisp is slow" is a myth. Most lisp compilers do _not_ use bytecode. SBCL compiles to fast machine code that can compete (and sometimes outperform due to presence of high-level facilities) with C code (including numerical computations). SBCL can often prove that arithmetics will not overflow register and perform various optimizations (including the most interesting cases with bit-twiddling).
"Most languages don't support bignum because of the code bloat inherent. C++ will likely compile these statements like:"
That's the problem in C++ compiler and the problem in its static typing (e.g., typing variables, not values). Lisp compiler will compile it into completely different code due to using tagged values (i.e., in most cases the runtime dispatch is _very_ fast).
There are usually 3 steps in creating software: make it work, make it right, make it fast. Using arithmetics in machine words screws the second step.
dmitry_vk on May 13, 2009 11:25 PMComputers are fine with math, it's the programmers that suck.
Jonathan on May 13, 2009 11:31 PMRaymond Chen wrote about how Calculator got an infinite-precision engine: http://blogs.msdn.com/oldnewthing/archive/2004/05/25/141253.aspx
(In my opinion, the biggest waste of development resources you could think of, but oh well.)
Frederik Slijkerman on May 13, 2009 11:34 PMIn discussion like these, people seem to forget 2 important things:
First:
Computers are only high speed idiots
Second:
People/Humans normaly calculate in decimals (in base 10), whereas computers calculate with floating point (in base 2), allthough both use some form of DOT notation, using floatingpoint in programms will allways give you errors in the real world with for instance 'money'.
"using floatingpoint in programms will allways give you errors in the real world with for instance 'money'."
The conclusion: do not use floating point for such values, but use precise rational arithmetics.
dmitry_vk on May 13, 2009 11:51 PMRuby and Python rules too :) Just like the python:
[ruby]
~$ irb
irb(main):001:0> 399999999999999-399999999999998
=> 1
irb(main):002:0> exit
[php]
~$ php -r 'echo 399999999999999-399999999999998 . "\n";'
1
~$
I got the correct answer from excel 2007 when I tried "=850*77.1"
Norbert on May 14, 2009 12:09 AMPython rulez ?
>>> 38.1 * .198
7.5438000000000009
>>> .1
0.10000000000000001
http://docs.python.org/tutorial/floatingpoint.html
I had the same problem on an e-commerce website in c#, and in perl/PHP/Tcl/C, and as everybody knows computers are not faulty, only developpers :)
Normaly to avoid problem it is quite better not to work in BCD (binary coded decimal) float (unless your CPU compute natively numbers in decimal :) ), but rather to use fixed point trick.
In real life it means manipulating only intergers (you don't store price as float, but integer representing tenth of cents for instance) and the point is just a matter of presentation.
It hardly works all the time, but it is better than nothing.
jul on May 14, 2009 12:13 AMComputers don't suck at math. People simply use floating point variables for purposes that floating point wasn't designed for.
The technology to do true decimal arithmetic and return precise numbers has existed for more than 50 years, On business platforms, such as the IBM i platform, it's the default numeric data type. It's the right choice when you are working with money, weights, quantities and the other precise numbers used in business.
Floating point was designed more for scientific applications or graphical applications. It wasn't designed for business.
Strangely, most languages for the PC platform are lacking true decimal arithmetic, and the developers aren't clamoring for it. I've never understood that. How can floating point be good enough for your business?
darkbagel on May 14, 2009 12:17 AMThe excel bug is very confusing ... if you take that 850 * 77.1 and format the cell as a date you get the same value as if you have 65535 formatted as a date ... if you format it pretty much any other way you get the 100000 and 65535
ChrisHDog on May 14, 2009 12:20 AMThe difference is: If a computer does a wrong calculation, it is caused by a bug in either hard of software. If a human calculates wrong, it is very likely caused by a mistake, lack of talent or too complicated math. Unless of cause that you define humans as bugs.
Reminds me of how brilliant I thought I was, when javascript:parseInt('010') returned 8 instead of 10 . "I have found a bug in javascript" I thought. Only to find out it was because of the octal conversion. :)
@jul I think you are confusing binary coded decimals (BCD) and binary floating point representation (IEEE 754):
http://en.wikipedia.org/wiki/Binary-coded_decimal
http://en.wikipedia.org/wiki/IEEE_754
BCD is (was?) a technique often used in assembly code to store large numbers and perform precise arithmetic on them.
Anders Sandvig on May 14, 2009 12:47 AMJeff, why do you insist on including some kind of image/clipart on *every* post you make? Occasionally they help make the post entertaining. More often than not it is simply annoying.
Joe on May 14, 2009 1:00 AMI'm a mathematician, and it is true that 0.(9)=1, but I hate that result. It's really annoying. If you want to get rid of it, you can use infinitesimals and nonstandard analysis, but they are tricky too.
But that's not really Jeff's point, since computer math doesn't even get close to being able to say that 0.(9)=1, unless you go all symbolic on me.
William on May 14, 2009 1:02 AMOne of my favorite rounding stories. During the first Gulf war, patriot rockets fired by the Americans got less and less reliable over time, and often missed their target. But strangely enough, the ones fired by the Dutch forces didn't.
Turned out, the Americans kept systems going all the time, whereas the Dutch, frugal as they are, switched them off at times when there wasn't any threat. When the Dutch switched them on again, systems reset, looked up the time on the network and were happy. But the Americans never reset, and the rounding errors caused real time and "kept track of time" to drift, causing them to aim in the wrong direction (because the clock was used to orient the systems).
Don't know whether the moral is be frugal or have more bytes in your time representation, but it seems to show that even addition (+ 1 second) canlead to problems.
Martin on May 14, 2009 1:26 AMItís good that you are acknowledging that it is important to know some mathematics, but I find this post slightly disturbing, in as far as it was felt to be necessary.
When I were a lad, learning my trade, one of the first things youíd learn was how computers represented numbers, and what that meant for precision. The fact that this post is needed suggests there may be a generation of programmers who donít care about whatís happening under the hood. Maybe dynamic languages are to blame, or maybe not enough programmers learn C.
In any event, as others have pointed out, the post is slightly misleading in that you donít mention that computers use binary, and the problem is that a fraction might have a low precision decimal expansion, but be infinite in binary.
Last time I was bitten by floating point arithmetic was calculating a triangle area with Heron's formula.
http://en.wikipedia.org/wiki/Heron%27s_formula#Numerical_stability
I've never have to care for those little errors with big numbers but in a naive implementation of Heron's formula a little disproportionate triangle results in semiperimeter equal to a side and 0.0 as resulting area.
901 on May 14, 2009 1:29 AMActually Excel 2007 has been fixed for a number of years now. Don't you keep your machine patched?
Also, the excel 2007 bug was a display bug, not strictly the same as the subtraction bugs shown in calculator and google.
Why do you always make such bland - and wrong - statements?
Anon on May 14, 2009 1:31 AMProgrammers should definately be aware computers do this and how not to step into the traps it opens.
For example when increasing a value with a small fraction to predict growth in the far future. Say your daily increase was calculated to d=0,00000000000000000001241224111244. So school math will tell us to take (1 + d)^100 to forecast the value 100 days from now. Using a float with not enough precision can cut off more decimals than expected when adding 1 to the very small number. If you instead add the increase day by day you'll get a different, more accurate, result value.
Stefan on May 14, 2009 1:48 AMAren't all numbers (other than crazy mathematical constants) representable by finite fractions ? Like 0.33333... is representable perfectly fine by 1/3, 0.1 by 1/10, etc ? Would be interesting to see if any work is being done on using such a data type to represent 'floats'.
J. Stoever on May 14, 2009 2:19 AM-[A standard floating point number has roughly 16 decimal places of precision]-
Assuming 'decimal places' means 'significant figures', this is the precision in a 64-bit double. You only get 6 or 7 significant figures from a 32-bit float.
Chris Johnson on May 14, 2009 2:20 AM@ J. Stoever: There are very many more [vast understatement] "crazy" irrational numbers than there are rational ones.
Dennis on May 14, 2009 2:41 AM@J. Stoever: Only rational numbers. That's why they are called "rational". Irrational numbers like pi, sqrt(2), etc are not representable by fractions, unless you round them.
That said, there are in fact libraries and even built-in mechanisms in many languages for handling fractions the way you describe. The only issue is that they are much slower, resulting in a precision-speed trade-off when considering the two.
Liquid_Fire on May 14, 2009 2:42 AM"When I were a lad, learning my trade, one of the first things youíd learn was how computers represented numbers, and what that meant for precision. The fact that this post is needed suggests there may be a generation of programmers who donít care about whatís happening under the hood."
Don't blame the tools/generation, blame the field. And if it's "this young slapdash generation", how come f-p bugs have been causing problems since before I was born?
I did Java long before messing with low-level languages, and this issue still arose, because I was doing something that involved floating point arithmetic. You can find this issue on a pocket calculator if you're doing the 'right' sum. But it's worth a reminder that it exists, that it's incredibly prevalent, and what it means for computing.
Or maybe Jeff just needed to fill his blog quota.
@Darren
0.99999... doesn't "approach" anything. It's a number. Saying it "approaches" 1 is like saying 1.1 "approaches" 1.2, it's clearly nonsense.
0.99999... = 1
noko on May 14, 2009 2:56 AM@Martin obviously the morale is to always run NTP daemons on your rocket launchers. :-)
@Steve W: number representation and all those basics are part of any decent comp sci program and I'd think you'd find it at a university level software engineering program too. Nowadays most programmers get trained in trade schools though. Not all of them teach the basics.
Though as someone pointed out, floating point arithmetics has its issues in dynamic languages too. Any decent language guide will contain a section on them so it seems to me most programmers would eventually get round to learning about them, one way or another.
wds on May 14, 2009 3:02 AM@Darren
0.9999... = 1
because
(10*0.999...)-0.999... = (10-1)*0.999... = 9*0.999...
and
(10*0.999...)-0.999... = 9.999... - 0.999... = 9
Thus 9 = 9*0.999...
Arithmetics axioms say if x*y=x then y=1 (1 is the unique neutral element for * operation).
Actually, you're talking about calculation, not math.
Rik on May 14, 2009 3:28 AMheheh, the vb guy said "dim"
mark on May 14, 2009 3:37 AMWorks on Live Search :)
http://search.live.com/results.aspx?q=399+999+999+999+999+-+399+999+999+999+998&form=QBLH
Blah on May 14, 2009 3:47 AM<i>"In mathematics, the repeating decimal 0.999Ö denotes a real number equal to one.", and "This equality has long been accepted by professional mathematicians and taught in textbooks."
Not the textbooks I read (or did when I was in university - it's not a favorite pasttime of mine...). The correct mathematical explanation is that 0.99999... (zero point nine recurring) approaches 1. Any pure mathematician (probably not many read Coding Horror...) would surely agree.
Good post, though!
Darren on May 13, 2009 10:47 PM </i>
Uhh... No. Any "pure mathematician" would know that a single number doesn't converge to anything.
Certainly, the <i>series</i> {0.9, 0.99, 0.999, 0.9999, ...} converges to 1, but that's just further proof that the <i>number</i> 0.999... is 1.
Consider this: If 1 and 0.999... are not equal, then there are an infinite amount of numbers between the two. I defy you to find one.
Asmor on May 14, 2009 3:52 AMI normally read CH in an aggregator, but came to comment about the Ariane 5 mention. Given the notoriety of the launch failure and its subsequent use in many undergrad CS/IT courses, it's not surprising that it has its own article: hxxp://en.wikipedia.org/wiki/Ariane_5_Flight_501
@Vinzent however beat me to it...the problem wasn't with the number conversion per se, but the inappropriate re-use of software from a different software project, without checking the design constraints properly and also without appropriate in-situ testing.
Jeff - misuse of previous code is a negligent act that should be talked about more, and with more attention than the Windows 3.1 calculator should ever get 17 years later.
Mark on May 14, 2009 3:58 AMGoldberg's "What Every Computer Scientist Should Know About Floating-Point Arithmetic" is a must read and must understand for every software engineer.
Also, it may be useful to read the relevant chapters of the Knuth's The Art of Computer Programming. It may be a bit dense for understanding, but it's good.
It's worth to note that besides the clear difference between the numeric models we learn in school and models employed in our computers, there's yet another one, specific to the design of programming languages...
Let's look at the basic C/C++'s problems with math, the problems with which plagued an incredible amount of existing software.
1. Signed types get promoted to unsigned where necessary and unnecessary. The following condition is always false (it evaluates to 0):
1U > -1
Yeah, nice, +1 isn't greater than -1. This is totally brain dead.
Although usually it's not cheap to compare signed and unsigned values, it's possible and I see no point in making the programmer do it in convoluted ways, which he very often (usually?) doesn't for one reason or another (laziness or ignorance) and ends up with a code bug.
2. Suppose our int is 16-bit long and our long is longer than that. Then the following condition is always false as well:
32767 + 1 == 32768
Sweet.
That's because the nums on the LHS will be ints, but the num on the RHS will be long per the language design. And per that same simplistic design there's no provision to avoid the overflow on the LHS when moving it into an lvalue (or comparing it with rvalue) that has more bits, where the overflow will become apparent and likely unwanted.
3. The following is false as well, also due to signed->unsigned conversion:
(-3) % 3U == 0
I'd love to see this produce mathematically more expected results at the expense of extra CPU cycles. Too bad it's not so.
4. Assuming 16-bit ints, the following will be false:
32767 * 2 == 65534
But these will be true:
32767L * 2 == 65534
32767U * 2 == 65534
It is obvious that the product of two 16-bit ints is gonna need 32 bits of storage. It is brain-dead to require the programmer to instruct the compiler to produce the full product and not just the least significant half of its bits or do some other trickery. It's easy to make a mistake here and forget an explicit type conversion to long of one of the multiplicands.
5. The following is also false:
-2 + 1U + 1.0 == -2 + 1.0 + 1U
(A+B)+C is no longer the same as (A+C)+B. Now, that's nice, broken commutativity!
6. Again, assuming 16-bit ints, shifts by 16 or more positions left or right are undefined per the design and in practice you get some funny results as if the shifts were done by count % 16. It would be natural to produce 0 with right shifts by 16 or more (assuming, we're talking unsigned ints, it's a different thing with signed ints) and I'd be OK to get a 0 (or anything defined, e.g. UINT_MAX) when doing the same in the other direction.
Basically, the problem is, in C/C++ a lot of what you learned about arithmetic is no longer true, not just the rational (AKA floating point) numbers. That is, you can't just use whatever you learned at school. You must learn the way the language does the math and you must write your code accordingly, adapting your ideal-world ideas to the brutality of the real computing. C's arithmetic expressions look familiar and seem to make sense to anybody understanding math, but make no mistake, behind this faÁade hides a great deception.
It's possible to explain in part why C/C++ is so goddamn math unfriendly. It's basically a generalized assembler language which must be quite primitive so it's easy to compile it and transform into comparable and primitive instructions of the target CPU. For instance, very few CPUs have comparison and division of a signed and unsigned operand. It is uncommon for CPUs to support shift counts larger than the register size in bits. It's possible to construct such operations, but nobody bothered to back when C was being designed and now it's too late.
Every C/C++ programmer has to learn this the hard way and figure out a way to do in C what an ideal (or almost so) calculator would do w/o any "surprises".
For a long time I actually found programming in assembly more transparent and giving more expected results than programming in C. In part I attribute it to the difference between the two: when you learn an assembly language you have to open the CPU manual to see what registers and instructions are there and how they work. In C you don't seem to need to learn how + or * or == work, because they're familiar and you intuitively know how to use them. Unfortunately, these are wrong expectations and assumptions, and wrong expectations and assumptions rarely work well in software engineering. What helps in the case of C/C++ is reading and understanding the language standard. The standard isn't an easy reader. Many usually end up buying books on C/C++. These days there're titles that cover the issues well. But I remember the days when C/C++ books covered this poorly or ignored the topic almost entirely. I hated them and only finally got everything straight in my head when I'd made every possible mistake and written a sufficient amount of very portable C code.
Btw, last time I checked, the C standard was available online for the mere $18 (cheaper than a book on C/C++ you'll pick at your local bookstore). Not knowing how to use your tools correctly is not just bad, it's very bad and wrong. At the same time I wish C/C++ never existed in its current form -- it could've been done better.
Anonymous on May 14, 2009 4:05 AMI never understand why some people have such an issue with 0.999Ö = 1, but never with 0.333Ö = 1/3. And given that, what do they think 3 X 0.333Ö is?
Steve W on May 14, 2009 4:29 AMThe Windows calculator issue went away when MS rewrote it to use infinite precision for basic operations...
http://blogs.msdn.com/oldnewthing/archive/2004/05/25/141253.aspx
Using real numbers, 0.999... is absolutely one. Limits are involved in the proof, but aren't necessary for the original statement. But, as pointed out by William, there are other number systems (hyperreal, superreal, surreal) that have an infinite number of numbers between 0.999... and 1. The defiance shouldn't be to come up with such numbers (in Hakenstrings, 10(1) followed by any combination of 0s and 1s), but rather to find a use for them in CS.
McBeth on May 14, 2009 4:45 AMWhat did you expect from Windows? On my Linux system, xcalc does the example correctly, even to 5.0002 - 5.0001. Ditto for command-line dc.
/smug
When I was a freshman my professor asked in our class to explain the behavior of
for (i = 0.2; i != 10; i++)
...
I was the only one to answer this question right and I got an extra point in my final exam!!!
VasandGVD on May 14, 2009 5:09 AM> Interestingly, the launch failure of the Ariane 5 rocket, which
> exploded 37 seconds after liftoff on June 4, 1996, occurred because
> of a software error that resulted from converting a 64-bit floating
> point number to a 16-bit integer. The value of the floating point
> number happened to be larger than could be represented by a 16-bit
> integer. The overflow wasn't handled properly, and in response, the
> computer cleared its memory. The memory dump was interpreted by the
> rocket as instructions to its rocket nozzles, and an explosion
> resulted.
As Vincent alreay pointed out, this is nonsense. What happened was that code from the Ariane 4 project was reused. The special thing about that was that it was proven mathematically that the input-values will never exceed the range, so that there was no need to check these boundaries.
Ariane 5 - that is much bigger than Ariane 4 - lead to the values exceeding this range resulting to an exception when executing the ADA-code and the shutdown of the specific computer. The secondary system taking over and processing the same data, shut down as well after running into the same exception leaving Ariane 5 without working stabilization system. The explosion was remotely initiated because of the rocket starting to become uncontrollable.
Hope that clears things.
Regards, Lothar
I think that a lot of the problem comes from 2 places.
1. Trying to fit such a large number of values into such a small space.
2. Using binary floating point rather than decimal floating point.
Firstly, a standard 32 bit floating point can represent a value as large as 3x10^38, and as small as -1x10^45. That's a really big number. Most applications, unless you're dealing with astronomy, or particle physics you will never need numbers that big. 99% of people probably would be good with a smaller range of numbers if they were more accurate. For the numbers that most computers deal with on a daily basis, 10^16 would probably be more than enough.
Then there's the issue of using binary floating point. This means that we can't even represent numbers such as 0.1. There's a lot of common numbers that can't be represented exactly. If we used a representation of the numbers that more closely mapped to the numbering system we used, then there wouldn't be so much of a problem.
So, I think that we should really be using something more like what is offered in databases in our programming languages. Something like the "Decimal" DataType. You can declare a field as Decimal(18,4), and you know that you can represent all numbers that are up to 14 digits before the decimal, and 4 digits after the decimal. You know exactly which numbers you can represent, and any person can understand that without getting into the complexities of converting from binary representations to decimal representations.
Kibbee on May 14, 2009 5:51 AM0.2 (or any non integer multiple) is the equalavent in binary as 0.3333333 in base 10.
This causes a ton of problems and is by any loop should use <= to stop the loop and not ==.
Also, about .999999999 being equal to 1, consider this.
1/9 = .1111111111...
2/9 = .2222222222...
3/9 = .3333333333...
4/9 = .4444444444...
5/9 = .5555555555...
6/9 = .6666666666...
7/9 = .7777777777...
8/9 = .8888888888...
9/9 = .9999999999... (WAIT 9/9 = 1 doesn't it?)
Tim's post is compelling.
Zack on May 14, 2009 6:00 AM*thinks some chum has been thrown in the water as he watches the sharks circle*
AC on May 14, 2009 6:12 AM[c#]
const float nine = 9;
for (float i = 1; i < 10; i++)
{
Console.WriteLine("{0}/9 = {1}", i, i / nine);
}
Console.ReadLine();
[/c#]
This outputs:
1/9 = 0.1111111
2/9 = 0.2222222
3/9 = 0.3333333
4/9 = 0.4444444
5/9 = 0.5555556
6/9 = 0.6666667
7/9 = 0.7777778
8/9 = 0.8888889
9/9 = 1
This may all be news to those who did not have a computer science education.
Sharks are jumping all over the place.
I also agree that (once again) Jeff misunderstands or over-simplifies - i.e. the Ariane comment.
tim on May 14, 2009 6:43 AMIt can only be attributable... to human error.
Tom on May 14, 2009 6:51 AMYour post reminds of a joke that I heard not long ago...
An infinite number of mathematicians walk into a bar. The first one orders a beer. The second orders half a beer. The third, a quarter of a beer. The bartender says "You're all idiots", and pours two beers.
@Darren - For most coders we have had just as much math as traditional mathematicians, and I am not sure where your school is but when I attended the University of Michigan it was taught that .999... infinitely repeating is exactly equal to one.
http://answers.yahoo.com/question/index?qid=20070821213704AASMKu0
sharms on May 14, 2009 7:01 AMI really don't think it has anything to do with the programmers sucking at math, it has to do with them sucking at testing. No one is going to anticipate that the computer will give a mathematical error on any particular line of code. Rather, we need to anticipate that it's going to do something unexpected SOMEWHERE due to a bug in our code or in the runtime we're using. The crime isn't that the NASA programmers didn't realize the loss of precision with the numeric conversion, it's that they failed to create a unit test approximating real world data that would have revealed the problem before a billion dollar spacecraft blew up.
Jonathan on May 14, 2009 7:08 AMHmm, doesn't seem anyone's covered this angle yet... I think the reason there isn't a widespread solution to this problem built in to every programming language yet (as someone else said, "programmers aren't clamoring for it") is because the vast majority of programmers don't know this problem exists. If more people knew about it, maybe they would be. Imagine if it were common knowledge among business executives that "any result coming out of a spreadsheet is suspect, depending on what numbers you used". It's a dirty little secret amongst us programmers.
It is after all, ridiculous that we as people are more "accurate" in storing numbers with large precessions than computers are. How do we do it? We use symbols to denote repeating, and we articulate this as fractions when a division doesn't yield a zero remainder. So when we divide 9 by 2 for example, we as people might write: 4 1/2. Simple, a string of 5 characters including the space. No precision problems. Why in this day & age we feel we must represent this in base 10 or base 2 is beyond me.
Now before you say that "strings are slow", yes, today they are. But we're starting to see specialized processors in computers. Sound components, dedicated to that purpose. GPU's, dedicated for visuals. Why can a computer not have a better Math processing unit to make it fast?
Math errors like this are just unacceptable to me. What it comes down to is that you can't just "trust" the computer - because for your average programmer to just be able to write code under all the pressures we deal with every day, we just shouldn't have to deal with such an obscure problem that can manifest itself in such scary ways, when we least expect it. I wonder how many software bugs (yet to be reproduced or fixed) are as a result of some stupid math error buried so far down the abstraction chain that our puny human brains have zero chance of eradicating?
One last point that scares me about this weakness of computers: it's not that "slightly less precision" will hurt us very often. Let's face it, infinite precision doesn't make something more practical, necessarily. The bigger problem is in equality tests, which are used for logic switches. What if I "press the button" (you know which button I'm talking about?) based upon whether A - B = 0 ? (and A or B are one of those wonky values mentioned above)
Big trouble. It's time EVERY language had a true Number class. If we need to bake it into the hardware to get us there, fine, do it!
Craig Fitzpatrick on May 14, 2009 7:17 AMThere is nothing wrong with math.
Computer hardware is binary. Software tries to cope.
Steve on May 14, 2009 7:19 AMYour audience is software developers.
Why are you explaining this?
Michael Reiland on May 14, 2009 7:52 AMJeff, did you even READ the article you linked to about the Excel bug? It has NOTHING to do with floating-point error, it's entirely a display bug. The result is computed correctly.
The problem is in the float-to-string conversion code, which was hand-written assembly for maximal speed. The bug appeared when porting it from Win16 to Win32.
With 16-bit instructions, when the AX register goes from 65535 to 65536, it overflows back to 0 and sets the x86's overflow flag (OF) in the FLAGS register. With 32-bit instructions, when the EAX register goes from 65535 to 65536, it does NOT overflow and does NOT set the OF flag in the EFLAGS register.
For some very particular floating-point inputs, the float-to-string function increments the AX/EAX register from 65535 to 65536/0. As a result, a branch that was taken in 16-bit code which predicates on the OF flag was no longer being taken in the 32-bit code, eventually resulting in the bug.
Adam Rosenfield on May 14, 2009 7:53 AMErr, it's not the test of the overflow flag, but rather a comparison against zero that causes the incorrect behavior with the 32-bit code but not with the 16-bit code. My point still stands, though.
Adam Rosenfield on May 14, 2009 8:10 AM@Anders Sandvig
To be precise I was refering to fixed point representation :
http://docs.python.org/library/decimal.html
http://msdn.microsoft.com/en-us/library/system.decimal(VS.80).aspx
it spares really a lot of problem when working on e-commerce.
I may have been confus(ing|ed) though :)
I just did not remembered there is no such thing as a language working in BCD only oooolllllddd computers (IBM).
That's the problem of being graduated from last century :)
It doesn't help that the real numbers are uncountably infinite, not merely countably infinite like the integers. At least with integers you can say "okay, you get to represent the first N above and/or below zero" and just make N large if needed. Any two different real numbers have an infinite number of other reals between them, so it's impossible to represent any nonempty segment of the real number line exactly.
Jim on May 14, 2009 8:20 AMI am afraid these two examples have only very little to do with precision.
In first case, I suppose, it was an optimization, where all the digits were comapred and if they were equall, result was 0. Obvious. However, last digit was forgotten. In pseudo C code:
int streq(a,b) { return (strlen(a)==strlen(b)) && ("all" strlen(a)-1 chars are equall); }
Common mistake, in either direction.
Second error - I guess Excell is keeping big numbers in an array of 16bit numbers, and as the result somehow (it is likely, here the precision played a role) happens not to fit in these 16bits (sign + real(0.1) > fraction(1/10) ), top bit has to be carried over and something is/was screwed up there.
Marian
Marian Csontos on May 14, 2009 8:37 AMNews flash: in our ongoing series, after discovering proper password salting, and after discovering the processor supervisor state/ring 0, Jeff Atwood now discovers floating-point numbers. In other news, programmers everywhere discover the bozo bit can also be flipped on an other fellow programmer.
Pierre Lebeaupin on May 14, 2009 8:45 AMMaybe this is the reason why this cheap calculator I bought a few weeks ago does some calculations completely wrong. 2060/3.8*3.8=1 according to that piece of crap. Even other cheap calculators don't have that problem.
Alex on May 14, 2009 8:55 AMAs Dennis mentioned above, 0.1 is a simple base 10 fraction that has a repeating form in base 2, i.e., 0.0(0011) where the part in parentheses repeats. 0.3 is another example: 0.0(1001). Thus, they cannot be exactly represented in IEEE arithmetic. I've made some base conversion tools for numbers with fractional parts available at
http://www.knowledgedoor.com/1/Base_Conversion/Convert_a_Number_with_a_Fractional_Part.htm
These can be very helpful in illustrating just how easy it is to run into numerical problems when switching between base 10 and base 2 representations.
Computers only suck at math when they don't use IBM COBOL packed decimal (BCD) fields ^^
To support precise math and to have it built in is two different things. C++ supports arbitrary precision math just fine when using GNU MP Bignum lib <http://gmplib.org/>, it just isn't java which has even kitchen sink built in
zokier on May 14, 2009 9:36 AMWithin the real number system, '0.999...' is, by definition, equal to the real number 'one'.
In other number systems things can be defined differently:
http://en.wikipedia.org/wiki/0.999...#Alternative_number_systems
As far as I know systems are 'best effort' approximations of reality.
You are making a 'modern' assumption based on incorrect data.
Unless proper correcting software is included, computers are terrible at math. They can do it in binary, octal and hexidecimal. Unfortunately, they can not do decimal math. (There is NO octal equivalent to decimal 0.05... period. Also, there is a major difference between negative zero (-0.00) and positive zero (0.00). Control Data used to manufacture a decimal computer, and these problems were not really a question. Since the Window take over of reality, precision decimal math has taken a back seat to 'enhancements' instead of true and accurate function.
In the olde tymes (when BAL and machine language were the only languages, and punch paper tape was high speed input... Computers had to have math functions programmed (oftentimes) since, if you really know the facts, computers can only add.
Writing functions to actually do math correctly, is a lost art. After all, Computers are great at multiplying and dividing!! Right!!!... er.. ummm...
No. They aren't. Not unless a human, with understanding and knowledge, fixes the basic problem... Computers are binary, and Binary, Converted to octal, doesn't function in decimal.
Launch a space ship, from earth, to ... Ummm. Mars... The error in the system, unless corrected for (have you ever heard of mid missions flight corrections??) will miss Mars, and not by a small factor.
Unary mathematics is almost unheard of, now days... I remember a thick tome that was required reading, to do flight plotting. Seems a negative zero will, according to the computer either be equal, or not equal to positive zero, unless Murphy said it ain't, and you better listen.
Mathematically speaking, if the remainder of a subtration is even 0.000... (999 more zeroes)...01, there is a difference. Unless the difference is zero (positive or negative) there is a difference! If there is a positive or a negative zero, they you have to know why and test to see IF the difference is significant. Not doing so, will create errors like you might not believe.
the old orang on May 14, 2009 10:02 AMHmm...
einstein:~ siuying$ irb
irb(main):001:0> 399999999999999-399999999999998
=> 1
irb(main):002:0> 12.51-12.52
=> -0.00999999999999979
irb(main):003:0> quit
einstein:~ siuying$ python
Python 2.5.1 (r251:54863, Jan 13 2009, 10:26:13)
[GCC 4.0.1 (Apple Inc. build 5465)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> 12.51-12.52
-0.0099999999999997868
>>>
In general, to the commenters who are saying that Jeff is speaking to the wrong crowd...
It's good that you had an excellent computer science education. But you seem to be failing to account for the common nature of these issues. Maybe Jeff is saying things that have already been said, but as long as these mistakes keep happening these things bear repeating. At the very top of the article, it's observed that Google has made this common, easily-corrected error (I say "easily-corrected" because with Guido van Rossum in their organization somewhere, you'd think they could make the search engine's math output at least as good as the default handler in Python). If Google's screwing up something this simple, maybe it's not as obvious to the average programmer as we think it is?
So perhaps the people who write common and widely-used software should improve their computer science education. And perhaps the people who comment on these articles should (http://drupal.org/node/29405) help by contributing to successful projects like Drupal.
Maybe computer science prowess and popular, successful programs are semi-independent variables.
And maybe in a world where they are semi-independent, the people who know what they are doing should get up off the backs of the people who try to educate the rest of us.
Mark Tomczak on May 14, 2009 11:10 AMThe only problem I have with the .99999... = 1 is that give me N number of 9's after 0.9 and I can give you an infinite number of number between that number and 1. Not necessarily on a computer but in theory.
osp70 on May 14, 2009 11:16 AMYou know the old saying ... garbage in, garbage out
Don't blame the poor unknowing computer. It's just doing what it's told, and following the rules its given to produce a result.
someone on May 14, 2009 11:19 AMTrickiest computer math gotcha I stumbled upon in reality: modulo repetition. Given a float x, think there's no difference between "x%1" and "x%1%1" (% being modulo operator)? Think again:
Python 2.6.2 (release26-maint, Apr 19 2009, 01:58:18)
[GCC 4.3.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> x=-1e-20
>>> x%1
1.0
>>> x%1%1
0.0
>>>
Jolly good. If you see somebody using floating point for currency representation, they surely don't know what they're doing. Beware bad text-books.
Decimal numbers are "coming back" to computers. There is a modern IEEE-standard for them, and hardware support is said to be coming for this standard. Even the software versions are actually quite fast, but most importantly, they're correct. There are implementations for C and C++ as well.
Mike Cowlishaw made the programming language REXX which actually uses decimal numbers, and he's done some important work on decimal numbers and the IEEE-standard. He's also the man behind the JSR-13 for BigDecimal in Java. Densely Packed Decimal numbers are a variance of Chen-Ho encoded decimal numbers.
Some links on decimal arithmetic on computers for those who are interested:
http://domino.research.ibm.com/comm/research_people.nsf/pages/cowlishaw.index.html
http://en.wikipedia.org/wiki/Mike_Cowlishaw
http://www.intel.com/technology/itj/2007/v11i1/s2-decimal/1-sidebar.htm
http://en.wikipedia.org/wiki/Densely_Packed_Decimal
http://speleotrove.com/decimal/
http://speleotrove.com/decimal/DPDecimal.html
Simply put: There is not much excuse for not doing math correctly on computers. I can understand why floating point arithmetic is wanted by Fortran/HPC/Science programmers, who at least for some systems need as much speed as they can get their hands on, but for anything else, decimal arithmetic is the way to go.
Anyway, it's a bliss to use a language which just does it correctly.
Dennis Decker Jensen on May 14, 2009 11:23 AM@zokier
So if Java is like a house, then C++ is like a house without a kitchen sink?
Sounds about right to me.. ;)
jasonmray on May 14, 2009 11:24 AMSo...you've found a problem. What's the solution?
Practicality on May 14, 2009 11:45 AM>In mathematics, the repeating decimal 0.999Ö denotes a real number equal to one. In other words: the notations 0.999Ö and 1 actually represent the same real number.
> This equality has long been accepted by professional mathematicians and taught in textbooks.
Really? Glad to know it gets taught; nobody taught that to *ME*. I swear, just a couple of months ago I was randomly thinking about periodic fractions and non-decimal bases (nothing better to think about... maybe that's why it took me so long to get married :-) ), and I stumbled upon this fact in total bewilderment. It was a clear, unmistakable and inescapable consequence of a few basic mathematical facts. How fun!
To me, the most interesting consequence is that our conventional numeric notation system (even with the use of "..." or the "vinculum" sign) is not a biyective representation of the set of Reals, even though for the longest time I had assumed it was.
Euro Micelli on May 14, 2009 11:47 AM@Craig Fritzpatrick
ìSo when we divide 9 by 2 for example, we as people might write: 4 1/2. Simple, a string of 5 characters including the space. No precision problems.î
Good luck when you want to calculate sqrt(2). Seriously, there are many rational classes, but I doubt any store them as strings.
@Jim
ìIt doesn't help that the real numbers are uncountably infinite, not merely countably infinite like the integers.î ... ì Any two different real numbers have an infinite number of other reals between them, so it's impossible to represent any nonempty segment of the real number line exactly.î
Thatís not just a problem with unaccountably infinite numbers; rationales are countable, but any two rationale numbers have an infinite number of rationales between them. But this isnít really the problem with representing numbers on computers ñ integers have just as much of a problem if they are sufficiently large.
Not related to floating point numbers: Stack Overflow has spoiled me. Everything on the internet needs to be able to be up-voted or down-voted. I read this article in Google Reader and for a split second was looking for the up-arrow to click on. Sharing or staring an article just doesn't feel the same as up-voting.
Scottie T on May 14, 2009 11:58 AM@Daren:
>The correct mathematical explanation is that 0.99999... (zero point nine recurring) approaches 1.
No, actually it has nothing to do with Limits. I know it looks like it, but it's not.
Here's a simplified version of what I stumbled upon:
1/3 = 0.33333...
2/3 = 0.66666...
Nothing weird there. Those two are clearly exactly equivalent. Now:
1/3 + 2/3 = 1
No possible doubt there. There are no limits or rounding involved. Therefore,
0.33333... + 0.66666... = 0.99999...
Which means that 0.99999... MUST therefore be an alternative (non-normalized) representation of "1".
Euro Micelli on May 14, 2009 12:00 PMThe identity, 1 = 0.999..., simply indicates that we can represent the number that we call 'one' as two different power series,
0 + 9/10 + 9/100 + 9/1000 + ...
and
1 + 0/10 + 0/100 + 0/1000 + ...
(This is simply the definition of our decimal expansion notation; if the trailing coefficients of the series are repeating zeros, we omit writing them for convenience.) Put another way, the equation, 1 = 0.999..., just says that two different sequences (the partial sums of the two power series above) converge to one.
"But subtraction can be anywhere from exact to completely inaccurate. If two numbers agree to n figures, you can lose up to n figures of precision in their subtraction."
This makes no sense to me, and neither this article nor the linked article attempts to explain it. Why should subtraction be harder than addition, multiplication, or division? I've tried thinking about it from various angles, and don't see why subtraction should introduce this kind of difficulty, and especially why the agreement of the two operands should have an effect on the precision of the results. Can you elaborate?
Joe on May 14, 2009 12:41 PMI really hate when some data type isn't good or large enough. When I do calculations, I am not interested in the datatype one bit. If the value is big, do you think I care? The computer should enlarge the variable to be able to hold the big value - automatically. Automation is the name of the game anyway.
Or do you think it is reasonable that when a big value occurs, the computer whispers me "hey, psst... hey programmer" "What?" "This is really embarassing, but could you kindly enlarge my variable?" "Oh for God's sake. Argh, alright then, but this will be the last time!" "Yes, goody goody goody! Thanks!"
Silvercode on May 14, 2009 12:56 PM"This makes no sense to me, and neither this article nor the linked article attempts to explain it"
Simple enough of a problem to understand that you are confused...
1. Computers are not user friendly.
2. Computers can ONLY add...
3. At that, they can only add 1+1... 1+0, or... 0+0. they add only binary integers (not decimals.)
4. Programming, either hardware, software or firmware, seemingly allow computers to do more, but, in essence, they only take the numbers and manipulate them to force the execution of subtraction, multiplication and division.
5. (here is where it gets complex) Subtraction is performed by forcing the number to become a negative value (called the compliment). and then they are added together to get the answer. That is a little hard to understand but, If you look at the equation 5 - 4, you see the same thing stated. You turn a 'positive' four, into a negative number (-4) and add them together to end up with a '1' (5 + (-4)= 1).
(before anyone sounds off...)
I am not a college graduate...
I used to be a very low level language programmer...
I had to read and comprehend a book on 'Higher Unary Mathematics' for a job I had dealing with navigation.
I may not be explaining things well, but, I know what is the essence of what I have said.
I used to have a sign on my desk that said:
"Your wisdom is akin to the result of the most complex and detailed problem in higher unary mathematics."
(ALL problems in ALL levels of Unary Mathematics are answered with "0", the only number in Unary Mathematics. The only problem about the answer was, is it negative or positive... and THAT answer took a whole book).
PS: If one understood the sign, it was not directed at them. But considering the environment and the job, you would be surprised how many didn't.
the old rang on May 14, 2009 1:24 PMJavaScript also passed this test:
<html>
<head>
<title>JavaScript Test</title>
<script language="JavaScript">
function doIt() {
var x = 399999999999999;
var y = 399999999999998;
var z = x - y;
document.write(z);
}
</script>
</head>
<body onLoad="doIt();">
</body>
</html>
Hmm I put that little Excel equation into Excel 2007 and got the correct answer of 65,535. Did I do something wrong???
Mike on May 14, 2009 1:36 PM"The only problem I have with the .99999... = 1 is that give me N number of 9's after 0.9 and I can give you an infinite number of number between that number and 1. Not necessarily on a computer but in theory. "
One problem with all the discussion, is that .99999...=1 is a mis-statement. It is 'Wrong', or more precisely, a mis-interpretation of what is symbolised.
A simple way (very simplified) is to say that 0.99999... is so close to 1.0, that I wish not to have to print all them darned nines, and for my purposes I will round it off to 1.0, so I don't have to spend all day writing out senseless nines. The precision of avoiding the incredibly small differences is not worth the effort, since each space is 1/10 the size of the previous.
BTW pi to the 10th position is precise enough to negate almost any need to go further, except to make one think pi to the millionth place is a good encryption tool. (and a nifty dandy way to test your abilities at programing decimal precision.)
the old rang on May 14, 2009 1:43 PMGoogle got this wrong:
$ perl -e 'print 399999999999999-399999999999998 . "\n";'
1
$
Python got this wrong:
$ perl -e 'print 38.1 * .198 . "\n";'
7.5438
$
Final Grade:
Google: 50% (F)
Python: 50% (F)
Perl: 50% (A+)
Perl Wins!
David W. on May 14, 2009 1:57 PMNot sure you calculator and Excel 2007 examples are 100% accurate. On my Win7 machine running Office 2007 the calculator and Excel examples return the correct values. I have emailed you screenshots of both, just so you can see that it appears those examples are not longer good examples. Other than that this was a really good article on how we as programmers need to understand how computers handle math.
Have a great day.
smehaffie on May 14, 2009 2:38 PMHi
Try query in google:
1 usd in dkk
RESULT: 1 U.S. dollar = 5.45538856 Danish kroner
and then try:
1 us dollar in dkk
RESULT: 1 U.S. dollar = 5.47321409 Danish kroner
A small difference... But could be more serious working with larger numbers ;-)
// WiredSource
WiredSource on May 14, 2009 3:30 PM@Pierre Lebeaupin
Well you think this is trivial the same way unicode, date/time, CRLF, typography are. But I am still surprised at how often I stumble on mistakes in computer expert codes I have to rewrite.
Seems recoding a framework fits the so called experts, real life non export developper as I have to deal with the so called trivial issues in their code.
So THIS is a great topic. As much as "dont put clear text password in database" as should be "try to use ISO, IEEE, RFC norms for representations".
For the record I was once told my application (talking to an international webservice) had a bug, because I did not use uk for the Great Britain country code (there is no such thing as Great Britain in os3166). Another time I was told "an" should be used for England country code.
Trivialities is the base of begining to know something, while expertise is the art of ignoring so called trivia.
While experts are told to have a narrow specialized culture, developpers should have a broad culture, that's why I like coding horror.
Great topic Jeff, thx.
Why does anyone need a calculator to see that the answer is 1?
mbhunter on May 14, 2009 3:46 PM1 and 0.999... are simply condensed notation for different infinite sequences that converge to the same real number. I think that the controversy about the 1 = 0.999... thing stems from the fact that most people do not think of a decimal expansion as the limit of a convergent sequence. Here's an excellent explanation:
http://en.wikipedia.org/wiki/Decimal_representation
Andrew on May 14, 2009 4:17 PMThat calculator bug existed for quite a while in windows.
It was still present in 3.11 WfW.
bram
At www.karenware.com you can get a freeware calculator program for Windows that will do calculations to hundreds of thousands of digits.
The bigger numbers will take a while.
I imagine it won't do infinite numbers of digits.
Joe wrote:
-----------
This makes no sense to me, and neither this article nor the linked article attempts to explain it. Why should subtraction be harder than addition, multiplication, or division? I've tried thinking about it from various angles, and don't see why subtraction should introduce this kind of difficulty, and especially why the agreement of the two operands should have an effect on the precision of the results. Can you elaborate?
--------------
Simple, you are right that subtraction is no problem on exact numbers.
But let's imagine you have a slight error from former results or
decimal-binary conversion:
3 => 3.000 000 000 1 (decimal arithmetic) and
2.999 999 999 => 3
The correct result should be 3-2.999 999 999 = 1e-9.
But the result of the computer is 1e-10 which gives us a relative
error of 90% ! The problem: The erronous digit which lumbers normally peacefully far far back in all operations and can be ignored slides forward if the preceding digits are erased and that can happen if you substract two adjacent numbers.
In a similar vein this was explained to me by a teacher who also was a priest which made it all the more funny...
A naked woman is standing 10 meters away from a mMathematician and an Engineer. They are allowed to walk halfway towards the woman before stopping then go half again and so on and so on...
The Mathamatician says you will never reach her.
The Engineer says you will get close enough as it makes no difference.
Paul on May 14, 2009 4:59 PMMathcad - by PTC - get's all these values right every time. I suspect Matlab, Maple and others do too.
That's why I use applications specifically designed for calculation when accuracy is required. Excel is a spreadsheet, and while powerful it doesn't doesn't have the riggor of a dedicated mathematics engine nor does it have a symbolic engine.
I love that joke by Paul.
Philip on May 14, 2009 5:36 PMI have had this issue. As a researching scientist I find errors in math all over the place. My TI-89 is one of the worst offenders. Labatory results can have huge errors because of this :(
Brandon on May 14, 2009 6:32 PMSmalltalk...
| i |
i := 399999999999999 - 399999999999998.
Transcript show: i printString
1
Simon on May 14, 2009 6:52 PMNo proof that 0.9999... = 1 is needed because they are equivalent by definition of the reals. :)
Of course this doesn't help most people upon first encountering this conundrum, but it's a reflection of the extent to which mathematics is a creation of humans. (Viz. the famous quote by Kronecker.) Perhaps a limit on the neo-Platonist view of mathematics.
Brian Tung on May 14, 2009 6:53 PMYou FAIL Jeff.
The correct question to ask the Windows Calculator is what is the difference between Windows 3.11 and 3.1?
The answer: nothing.
PRMan on May 14, 2009 6:56 PMWhat scares me is when people code money values as floating-point - I've even had an argument with a consultant running a Java course for Sun over this.
Kerry on May 14, 2009 7:20 PMosp70:
What you say is true, but backwards. What you're missing is we aren't giving you N many 9's in 0.999.... We're putting infinitely many 9's there. You cannot give any number with more 9's than infinity many 9's, so you cannot give a number between that and 1, which means there is no difference.
1/1, 2/2, 5/5, 9/9, multiplicative identity, 1/2 + .5, all mean the same thing, but people get hung up on this one representation of the number 1.
Ens on May 14, 2009 8:02 PMYou know, that 0.9999 would only be accurate if it produced a graphic that would reach the edge of the screen and beyond :-)
tomc on May 14, 2009 8:06 PM@the old rang:
I hate to "sound off" on that, but it isn't a "very simplified" way of looking at 0.99999... vs. 1, that's a wrong way of looking at 0.99999... vs. 1. Because the point is that they are literally the same number expressed in two different ways. Not so close as makes no difference, but the exact same number.
I'm an engineer. I know intimately "close enough as makes no difference".
Anonymous on May 14, 2009 8:15 PMtomc:
Not true! For the exact same reason that 1 + 1/2 + 1/4 + 1/8... doesn't equal infinity even though you are adding together an infinite number of positive numbers, it also doesn't need to take infinite space to represent the concept given infinitely fine pixel density (which could be approximated procedurally via an infinite zooming algorithm).
Alternatively, he could replace the graphic with the numeral 1 :).
Ens on May 14, 2009 8:22 PMObligatory Bistromathics reference:
"Bistromathics itself is simply a revolutionary new way of understanding the behavior of numbers. Just as Einstein observed that time was not an absolute but depended on the observerís movement in space, and that space was not an absolute, but depended on the observerís movement in time, so it is now realized that numbers are not absolute, but depend on the observerís movement in restaurants."
http://www.tudy.ro/2007/07/10/the-bistromathic-drive/
http://en.wikipedia.org/wiki/Starship_Billion_Year_Bunker
crap I still remember when stupid int counters would overflow at 32k and unsigned shorts were 256.
Trudy on May 14, 2009 8:57 PM"I hate to "sound off" on that, but it isn't a "very simplified" way of looking at 0.99999... vs. 1, that's a wrong way of looking at 0.99999... vs. 1. Because the point is that they are literally the same number expressed in two different ways. Not so close as makes no difference, but the exact same number."
Hmmm... hehehehe... Ok, engineer... Take 1.0. Subtract your number0.99999. Test for 'zero' and if it passes the test, when you are between the moon and Mars, you are right, and complete your mission. if you are wrong, you find temperatures in the solar range, and you ... should go to the sun when it is night.
The numbers are the same, by convention, NOT mathematics. People did not deal with such long decimals in olden times. (when the rules of mathematics and arithmetic were developed.)
Better still... make a gamble out of it. If the odds are that you have a 0.999999... chance of surviving an ordeal, you might take the bet... But, the odds are not 1.0... not a certainty. Would you still chance the bet? Murphy wrote the laws. The important one was 'at the worst possible time'... If certainty is required, 1.o is NOT equal to .99999...
the old rang on May 14, 2009 9:16 PMI do agree that infinite precision math is required in end-user applications (besides maybe matlab/mathcad and alike).
One can easily guess that Jeff is a little biased against Microsoft by not finding in his post this link
http://search.live.com/results.aspx?q=399999999999999-399999999999998&mkt=en-US
And this link http://blogs.msdn.com/oldnewthing/archive/2004/05/25/141253.aspx
Ruby did not exist and and Google was a very small startup when Microsoft fixed this "bug".
Unlike "strange" floating point caluclation, 850*77.1 trick in Excel was a real bug. Fortunately, I've just tried that trick in Excel 2007 SP2 and could not reproduce the issue.
Since nobody mentioned Haskell so far: Haskell is another language that handles large numbers and fractions very well. It even has a rational number datatype that represents numbers as the quotient of two integers of arbitrary size.
Kim on May 14, 2009 10:22 PM@the old [o]rang:
"A simple way (very simplified) is to say that 0.99999... is so close to 1.0, that I wish not to have to print all them darned nines, and for my purposes I will round it off to 1.0, so I don't have to spend all day writing out senseless nines. The precision of avoiding the incredibly small differences is not worth the effort, since each space is 1/10 the size of the previous."
At the risk of enabling a troll, let me correct you.
"0.999..." is not *pretty close to* one. It is one. Not by convention, not by habit, not by agreement, not by tradition, not by laziness. The problem here, I think, is that you are ignoring what that "..." means. It doesn't mean "a whole bunch more", nor "an arbitrarily large number of". It means an *infinite* number of. It means they go on forever. Not till you get tired of writing them, or holding down the 9 key. *For*. *Ever*.
What's more, your rambling about "positive zero" and "negative zero", about how "computers can only add, the rest is just tricks", and "computers can't do anything but binary" make me think you're a representative from the Time Cube organization. Look up bignums and BCD and get back to us. (Or don't.)
Atario on May 14, 2009 10:32 PMTo be clear, for all of those talking about languages that will handle this, and how PHP, lisp, Ruby, Python, etc. are all superior because they handle it, this isn't special. I'm not aware of any programming languages which would be unable to handle it. The integer in question requires 49 bits, what programming language still in use doesn't have 64-bit integers?...
The problem only exists because Google is using single-precision floats for this, presumably because they are able to get things done faster that way on average for a typical query. If your language can pass this test while using single precision floats, THAT would be impressive... But it can't. I highly doubt Google even sees this as a bug of any sort, because most users aren't exactly using the Google calculator in ways that would make this any more than a novelty. The fact that everybody looks at "399999999999999-399999999999998" rather than "30347423581692-303474235816991" or something from a real world example that went bad is a testament to this.
Tiak on May 15, 2009 1:42 AMThere is problem with Daren's explanation
>> 0.9999... = 1
>> because
>> (10*0.999...)-0.999... = (10-1)*0.999... = 9*0.999...
>> and
>> (10*0.999...)-0.999... = 9.999... - 0.999... = 9
But,
(10*0.999...(N-times)) - 0.999(N-times) = 9.999...((N-1)times) - 0.999(N-times) = 9.000...((N-1)-times)1 != 9
>> Thus 9 = 9*0.999...
>> Arithmetics axioms say if x*y=x then y=1 (1 is the unique neutral element for * operation).}}
confused on May 15, 2009 6:34 AMBased on the definition of decimal representation of real numbers, it's clear that 0.999... = 1. That's not what I have a problem with. Many posters, in making this claim, have appealed to the "obvious" notion that 0.333... = 1/3. My question is, if you don't accept that 0.999... = 1, then on what basis would you accept that 0.333... = 1/3?
mkorman on May 15, 2009 7:15 AM"if you don't accept that 0.999... = 1, then on what basis would you accept that 0.333... = 1/3?"
I don't know why they don't accept 0.999... = 1, but there is a more intuitive reason why 1/3 = 0.333...; just try dividing 1 by 3 using long division.
Steve W on May 15, 2009 7:49 AMJust some thoughts as a mathematician. Sorry about my English.
There's a huge difference between INFINITE precision and ARBITRARY precision. An arbitrary-precision system is able to represent numbers at any FINITE precision, but not at INFINITE precision -- it would not be able to handle all real numbers even with infinite memory. Actually, it could handle hardly any real numbers. There's just too much of them.
http://en.wikipedia.org/wiki/Cardinality
About the 0.999... = 1 confusion: just forget all the "proofs" and equations. Just check the definitions of decimal notation and real numbers.
lisaaKaljaa on May 15, 2009 7:52 AMI'd say that 0.333... does not equal 1/3. Its an approximation.
JC on May 15, 2009 7:58 AM"I'd say that 0.333... does not equal 1/3. Its an approximation."
Well, it's not like it's an opinion. Either it does or it doesn't. And, it does. Again, by the *definition* of decimal representation. Look up this definition if you don't believe me.
"I don't know why they don't accept 0.999... = 1, but there is a more intuitive reason why 1/3 = 0.333...; just try dividing 1 by 3 using long division."
But still, it's a leap to get from the finite iterative process of long division to an infinitely long number. I'd say that most people who are hazy on any of these facts simply don't understand what decimal notation even means.
mkorman on May 15, 2009 8:06 AM"I'd say that 0.333... does not equal 1/3. Its an approximation."
So what is the margin of error?
Steve W on May 15, 2009 8:07 AMWow, that is like WAY cool!
RT
www.whos-watching.net.tc
"But still, it's a leap to get from the finite iterative process of long division to an infinitely long number."
But I think that if you work through the long division process, it should be obvious that you are going to be dividing 10 by 3 with ramainder 1 for ever.
I mean if it's a finite process you would have to assume something is going to change to put an end to it.
Steve W on May 15, 2009 8:10 AM"But I think that if you work through the long division process, it should be obvious that you are going to be dividing 10 by 3 with ramainder 1 for ever."
You're right, but once people are able to accept the idea that a decimal number is actually the limit of some sequence (whether or not the sequence contains the limit), then you've already won them. Most people seem to have trouble getting that far.
mkorman on May 15, 2009 8:13 AMYou simply need computers to represent 0.999...(recurring) differently that 0.999999999999999999999999 (full stop). That could be done via metadata, for example, or an extended bit field, a digital equivalent of having a bar over the digit in human readable terms. Of course, once you start down this road, you'll end up with an operating system, or at least a libm, that resembles Mathematica more than anything else (which may or may not be a good thing depending on your sensibilities).
Jean-Michel Smith on May 15, 2009 8:15 AMPrivate Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click
Dim o1 As Double = 399999999999999
Dim o2 As Double = 399999999999998
MsgBox(String.Format("{0}-{1}={2}", o1, o2, o1 - o2))
'' 399999999999999-399999999999998=1
End Sub
VB.NET wins.
anders on May 15, 2009 8:15 AMRPGLE on the IBM AS/400 says it equals 1....Seems like Windows and Microsoft doesn't think anyone will calculate numbers that large...hmmmm
d Result s 16 0
/free
Result = 399999999999999 - 399999999999998 ;
dsply result;
*inlr=*on;
return;
No, the gravitational constant is known to much more than 4 significant figures - 14, I believe.
Ephilei on May 15, 2009 8:22 AMThis is a perfect example of where discrete representations fail where true analog would have no problem.
Just a thought :).
Practicality on May 15, 2009 8:28 AMMy XP machine running Office 2007 got the calculator and Excel problems right. I don't know what you're doing wrong buddy.
Matt on May 15, 2009 8:43 AMYou mean you didn't know IEEE representations????
DawnOfWar on May 15, 2009 8:44 AM0.9 (periodic) is equal to 1. That is mathematic and has nothign to do with cmputers. another representation is 9/9, and the difference between 0.999999999999999999999999999...9 to 1 is infinitisimal low. So both numbers are the same by math, not conventions (had a discussion with a dr in math & phys a while ago about this topic ;-) )
DawnOfWar on May 15, 2009 8:49 AMwow. i didn't know computer will make mistakes.
Steph on May 15, 2009 8:55 AMtype "bc -l" in a shell... problem solved ;-)
Alex on May 15, 2009 8:57 AM@Steve W
When I went through university for comp sci (less than a decade ago), I took an entire semester-long course on dealing with computer representations of real numbers and the consequences of floating point arithmetic. Take heart!
Cole on May 15, 2009 9:00 AM0,9 periodic plus an infinitely small fraction equals one. Only if you assume "infinitely small" to be zero you can say both numbers are equal.
It's a religious thing.
Amorpheus on May 15, 2009 9:00 AMworks correctly on kcalc under kubuntu 8.10.
Mike McGinn on May 15, 2009 9:12 AMHey does anyone know how to do quad-precision integers in C or 86 assembler? I spent a few weeks trying to do it and failed...
P.S. 128 bit number.
Steven Wagner on May 15, 2009 9:14 AMI talked to a Triple PHD in math who also worked at BK flipping burgers to cover a divorce... a number is a number is a number... they don't mean nothing till you say they do. If all you need is x Signif Digits... then cut it. Lame arguments for no reason. Computers do what you ask 'em to do. Ask them to do things corectly. MoveOn.org.
And anyone who does something based on time and doesn't take pains to keep things synched... idiota. Hope one of them missles finds THEM.
ShamWow on May 15, 2009 9:20 AMComputers dont make mistakes.....
They are perfectly logical and do exacly what they are told
problem is they are sometimes told the wrong thing!
SJenkins on May 15, 2009 9:30 AMI hereby comment on this particular post by [author]. There are two possibilities:
1. [author] is right. Any person that has previously pointed out the truth of the post has done so without necessity, as [author] stated an obvious fact and thus only wasted my time. Any person planning to point out the truth of the post after I did so should instead agree with me, giving proper credit to my intellect. Any person that has previously claimed that [author] was wrong should consider themselves responded to with alternative 2.
2. [author] is wrong. Any person that has previously pointed out the falsity of the post has done so without necessity, as the author is obviously incompetent (concerning this particular matter, and thus concerning any topic whatsoever) and only wasted my time. Any person planning to point out the falsity of the post after I did so should instead agree with me, giving proper credit to my intellect. Any person that has previously claimed that [author] was right should consider themselves responded to with this very paragraph.
I have made my opinion clear, and I have an anecdote that backs up my statement without the slightest possibility of a doubt. Go home now, there is nothing more to see here.
Ben on May 15, 2009 9:35 AM@Dennis
From my understanding, 0.9999..... does not equal one, but is generally accepted and taken as correct to equal its value to 1 given that the spatial difference between the resulting 0.99999...-1, is infact so small that it becomes inconsequntial.
Alvaro Fernandez on May 15, 2009 9:52 AMits all abt 16-bit and 32-bit thing.. calculator that u used is from Windows 3.11 or earlier.. use calculators of WIndows XP/Vista and see..
Dhaval Faria on May 15, 2009 10:05 AMFor the excel dudes:
SP1 fixed the issue.
your Excel 2007 example is wrong. It gives the right answer. That's cos MS developers are much better than google's smart arses
Michelle Rodriguez on May 15, 2009 10:20 AMwhy do cars suck at driving?
driver must know car's limitations, otherwise driving is not safe.
lanG on May 15, 2009 10:26 AMyour excel is crap
Michelle Rodriguez on May 15, 2009 10:44 AMhahahaha, nice topic. . .well, they dont suck, Microsoft does.;)
evan Varsamis on May 15, 2009 11:05 AMI thought that I am bad at math
antifreeze on May 15, 2009 11:05 AMJust found out that 5.3 - 5.0 = 0.2999999999999998 for both Firefox and Safari's JavaScript engines.
martoche on May 15, 2009 11:05 AMHere's how I've always thought of the .(9) = 1.0 argument. Basically there is no room between 1 and .(9). People say that you could fit .(0)1 in there, but you can't. It's infinity .(9) means every column or place is filled with the maximum value, that's why it's equal to 1. Who knows if that will make sense to anyone else, but it's always helped me understand.
Jason on May 15, 2009 11:48 AMWe know that the maximum of \sum_{n=1}^\inf x/10^n , x \in {1,2,3,4,5,6,7,8,9} is equal to 9* \sum_{n=1}^\inf 1/10^n. If we 'cheat' and use the definition of a convergent geometric series, that is for r < 1, r^n converges to (1/(1-r)), 10^-n is equivalent to 1/9. Then, 9*(1/9) is equal to 1.
Rob on May 15, 2009 11:59 AMActually, it was Ariane-4.999...
Shut the Float Up on May 15, 2009 12:00 PMwhere can I download the VM with Windows 3.0? hahahahaha
securityhorror on May 15, 2009 12:23 PMI think what Darren meant was:
starting with:
x = .99999...
10x = 9.99999... (multiply each side by 10)
10x - x = 9.99999... - .99999... (subtract x or .99999... from each side)
9x = 9 (simplify each side's subtraction)
x = 1 (divide by 9)
Q.E.D.
Wayne Goode on May 15, 2009 12:26 PM"Here's how I've always thought of the .(9) = 1.0 argument. Basically there is no room between 1 and .(9). People say that you could fit .(0)1 in there, but you can't."
Heh, right, I forgot many people claim that you could fit 0.0...01 in there. I think that understanding why 0.0...01 is nonsensical notation is equivalent understanding why 0.999... = 1.
mkorman on May 15, 2009 12:26 PMGoogle will give you the correct result until you increment beyond these values:
333333333333334-333333333333333
jon
Jon on May 15, 2009 12:43 PMactually you re saying it works on live search, but its capacity isnt infinite either, since :
http://search.live.com/results.aspx?q=39999999999999999999+-+39999999999999999998&go=&form=QBRE&filt=all
this error is not due to the precise value of 399 999 999 999 999, it's just because it's a big number, nothing exceptional.
btw nice proof Rob !!
LoÔc on May 15, 2009 12:59 PMFloating-point problem has already been fixed by Dr Larry Nylund at the Institute of Mathematics and Statistics; http://www.math-solutions.org
His intelligent implementations of desktop PC calculators have solve the floating-point problem. Dr. Larry Nylund's solutions are pretty good to solve math stuffs.
These are perfect mathematical solutions for school, high school, university and engineers.
Hans Adamsson on May 15, 2009 12:59 PMThese responses scare me very much.
How could this article be written without a discussion of machine-epsilon?
The desktop calculator designed by Dr. Larry Nylund is a complete replacement for the traditional calculator that comes with Microsoft Windows(c). It solves the issue of the floating-point problem.
Download your own desktop calculator today, at almost no cost! http://www.math-solutions.org
Lillian Travaglini on May 15, 2009 1:34 PM1/3 = 0.333333333....
multiply both sides by 3
1 = 0.9999999.....
don't be a d-bag
jerk on May 15, 2009 1:38 PM[0.(9) equals 1] is false.
[0.(9) does not equal 1] is also false.
[0.(9) is probably equal to 1] is true.
Probability is used to solve unsolvable problems. For 99.(9)% of our needs [0.(9) equals 1] is true. This includes engineering and applied mathematics. And it's for the simple fact that you have to decide on a level of precision (number of decimal places) or wait for eternity as the 9s roll out, and thus never get anything done.
In theoretical physics [0.(9) does not equal 1] is true. Think big questions like the size of our finite universe and what's on the other side if it is finite. In this context, 0.(9) does not equal 1.
It equals 42. :P
Shane on May 15, 2009 2:15 PMshane is being a d-bag
jerk on May 15, 2009 2:19 PMYou should know that
a) programming language "a is slower/faster than b",
b) programming language "a is better/worst than b",
c) 0.9 periodic vs 1 discusion (added right now),
are tabu subjects. It's too late now. This will go on and on forever.
you people need to learn numerical methods before commenting on this. numbers to a computer don't exist on a continuous line everything is discrete and not linearly space on that discrete number line. this sort of floating point error is a common occurrence for poorly written code
chris on May 15, 2009 3:40 PMWow, this is pretty pointless. Who gives a damn.
Brian on May 15, 2009 3:41 PMand furthermore, Ihave tested and retested this theory with the calc in XP and I cannot recreate a math error with any calculation period no matter what level of precision or how many digits.
Brian on May 15, 2009 3:43 PM@Lilian, Adamsson:
From the site:
------------
Desktop calculator handles resulting floating-point values between 2.225E-308 (2-1022) and 1.797E+308 (2-1024).
-------------
It IS floating-point. So stop spamming.
@Brian:
<a href="http://www.codinghorror.com/blog/archives/001208.html">http://www.codinghorror.com/blog/archives/001208.html</a>
XP uses now internal decimal math.
No Wolfram|Alpha handle it properly.
I guess it depends on the nature of the "computer"
Wolfram|Alpha uses at max only 66 decimal digits :(
http://www.wolframalpha.com/input/?i=(1%2B1e-66)^1e66-1&asynchronous=false&equal=Submit
Listen.
Anyone who says that .(9) is not 1 is mistaken or ignorant.
There is no mathematical question.
.(9) doesn't "approach" 1. Numbers don't approach. Variables do. Take some rudimentary calculus.
.(9) IS 1. They are IDENTICAL in the real numbers.
Take it from a mathematician.
Daniel Kaplun on May 15, 2009 8:25 PMThis really pisses me off. Why do you put your faith in the WRONG answer (yes, it is WRONG) when you have no logic to back it up?
I feel that we should teach middle-school teachers that .(9) = 1 and explain why so that an 8th grader would understand. Then there wouldn't be this retarded farce.
Daniel Kaplun on May 15, 2009 8:29 PMhttp://mathforum.org/dr.math/faq/faq.0.9999.html
Daniel Kaplun on May 15, 2009 8:31 PMIt's not a math problem, or even a generic computer issue. It is a developer issue. The floating point format was developed for compact storage and fast processing on x87-type coprocessors when power was scarce and memory was too.
The only legitimate way to perform any kind of business computation these days is to get rid of that encoding, realize that computers are a few million times more powerful now than they were then, and use ways to pack data that do not produce computational artifacts. Like the BCD encoding, for example. Which existed way before the x87 coprocessors.
With the sheer number of posts on this article there sure are alot of math nerds out there! I'm not complaining, just point it out!!
Nick on May 15, 2009 9:17 PMQED
sco3tt on May 16, 2009 12:24 AMQED
sco3tt on May 16, 2009 12:27 AMI tried it on calculator in windows 3.1 and it gave the correct answer.
Television Spy on May 16, 2009 12:59 AMWho is the audience for this? You're always making these bad arguments and missing fundamental concepts. I recommend taking some courses in computer science; this is actually discussed in excruciating detail in any reputable introductory CS course.
Charles on May 16, 2009 1:07 AMso funny! :)
ABCoder on May 16, 2009 2:12 AMSpotlight calculates 399999999999999 - 399999999999998 just right :)
I'm a Mac :P
I've accepted that 0.999... = 1
but I'm wondering what number would be "just" less than one to the infinitely-small number place?
ignorant 8th grader on May 16, 2009 6:44 AMI'm using Ubuntu. I get a perfectly correct answer :)
Jack on May 16, 2009 7:16 AM$ python
Python 2.5.2 (r252:60911, Jan 4 2009, 17:40:26)
[GCC 4.3.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from decimal import Decimal
>>> print Decimal('399999999999999') - 399999999999998L
1
>>> print 399999999999999L - 399999999999998L
1
>>> Decimal("38.1") * Decimal("0.198")
Decimal("7.5438")
>>> Decimal("0.1")
Decimal("0.1")
Goodness, you can prove 0.(9)=1 just using GCSE maths to find what fraction a recurring decimal represents. Basically, multiply 0.9999... by the period of the recurrence (ie 10), to get 9.9999... Then subtract the original number from it. So you obviously have 9 as multiplying 0.9999... by 10 won't alter the nos after dec. pt. Becos 9.9999...=10 times the no, 9 = (10-1) times the no. So 0.9999... = 9/9 = 1. Worked this out without even looking at the wikipedia page.
JH on May 16, 2009 8:56 AM@Ben
"I hereby comment on this particular post by [author]. There are two possibilities:
1. [author] is right. Any person that has previously pointed out the truth of the post has done so without necessity, as [author] stated an obvious fact and thus only wasted my time. Any person planning to point out the truth of the post after I did so should instead agree with me, giving proper credit to my intellect. Any person that has previously claimed that [author] was wrong should consider themselves responded to with alternative 2.
2. [author] is wrong. Any person that has previously pointed out the falsity of the post has done so without necessity, as the author is obviously incompetent (concerning this particular matter, and thus concerning any topic whatsoever) and only wasted my time. Any person planning to point out the falsity of the post after I did so should instead agree with me, giving proper credit to my intellect. Any person that has previously claimed that [author] was right should consider themselves responded to with this very paragraph.
I have made my opinion clear, and I have an anecdote that backs up my statement without the slightest possibility of a doubt. Go home now, there is nothing more to see here."
So...in other words....as much as you want us to agree with you and go home...in both alternatives YOU wasted time. Well...I'm willing to agree with you on THAT ahahaha
@everyone
I am amazed of how this thing got blown out of proportions but 0.9999.... is =1 and to answer Daniel Kaplun and his frustration I ensure you, where I come from they teach this fact in ELEMENTARY SCHOOL.
There is an important difference to be made here. I agree that in virtually every programming course I took this issue is discussed, in some texts more than others...but like many other semi-theoretical disciplines (like sometimes physics, and especially math)in software engineering sometimes for OUR ease and peace of mind this little detail gets forgotten and such errors ARE present in many software programs considered otherwise "bullet proof", and they go often undetected.
The very idea of relativity was conceived, by a man that we all know and revere....and we hold this principle to be true..and so far we have found it is so. However few people realize that before the important "discovery" of time-warp was made by Einstein HE TOO had to get rid of things like air-friction and aerodynamic forces to deduce the time-warp effect in his mental experiment of free falling objects that eventually led to the significant change of how we view the world of nature.
Every day in any school at any level you will see problems, even test question where they will say "Omit the windchill factor..." or "Discard air friction..."
It is in our very nature to try to make problems simple so that we can solve them. And this mindset has brought us great strides in understanding, technology, etc. I.e. it does not ALWAYS have to be perfect.
With that said, I recognize that this can be a problem when precise calculations are critical, and it should be and it HAS been addressed in those particular and special fields. But I think us common mortals are going to be fine with the variable sets we have.
And to those who criticized this author for pointing out this problem deeming it a waste of a blog well. I urge you to consider this is not paper and no trees were armed in the making of this post and stating the obvious has proven IMMENSELY useful in our scientific history.
Think about the origin of the word Eureka, spoken by Archimedes after witnessing a simple everyday life phenomenon (the raising of the water level when a body is immersed in it).
And remember the age old programmer's axiom the KISS concept...so please...let's!
_@EricDraven on May 16, 2009 9:48 AMI'm sure someone else picked up on this: "So any prospects of storing any infinitely repeating number on them are dim at best."
Wrong! You forget symbolic representation... I can store pi to perfect precision in a single byte! :)
Seriously though its good to be reminded that floating point numbers have all kinds of weirdness. The rounding errors are often missed by newbies, along with other things like how NAN and +/-INF react when put through conditionals. :)
Jheriko on May 16, 2009 12:40 PMsorry for a double comment but i feel obliged to point out, all of the examples you give are bad programming and not the computer's fault. :)
bad programmers...
the only thing i can think of along these lines is the old intel fpu bug with fdiv (long since fixed).
Jheriko on May 16, 2009 12:46 PM@ignorant 8th grader
"I've accepted that 0.999... = 1
but I'm wondering what number would be "just" less than one to the infinitely-small number place?"
One might be tempted to try 1 - 1/∞, but that equals 1, as does subtracting the smallest non-negative real number, which is zero (the same as 1/∞).
http://en.wikipedia.org/wiki/Infinitesimal
Dennis on May 16, 2009 12:50 PMThose "∞" are supposed to be infinity symbols.
Dennis on May 16, 2009 12:51 PM@the old rang:
"Hmmm... hehehehe... Ok, engineer... Take 1.0. Subtract your number 0.99999. Test for 'zero' and if it passes the test, when you are between the moon and Mars, you are right, and complete your mission. if you are wrong, you find temperatures in the solar range, and you ... should go to the sun when it is night."
We aren't talking about whether 0.99999 is equal to 1. We are talking about whether 0.99999... is equal to 1. 0.99999... is NOT a way of saying "I don't want to write all those damn nines but they do stop somewhere". The point of the representation is there is no end to the 9s. There are compact representations for enormous numbers of nines that eventually end in 0 without having to write all those damn nines.
What it is, is a stupid way to write the number 1. Stupid because it takes more writing and obviously confuses people. Another stupid way to write the number 1 is -e^(i*pi).
"The numbers are the same, by convention, NOT mathematics. People did not deal with such long decimals in olden times. (when the rules of mathematics and arithmetic were developed.)"
The numbers are the same by mathematics, and not convention (except inasmuch as mathematics IS convention).
This has nothing to do with how many decimal places people dealt with in the olden times. Besides, we've dealt frequently with infinites and infinitesimals for over 300 years with the advent of Calculus. And even before Calculus the infinite was not unknown in mathematics. It's not a modern development.
"Better still... make a gamble out of it. If the odds are that you have a 0.999999... chance of surviving an ordeal, you might take the bet... But, the odds are not 1.0... not a certainty. Would you still chance the bet? Murphy wrote the laws. The important one was 'at the worst possible time'... If certainty is required, 1.o is NOT equal to .99999..."
I would take the bet if there was any gain to it. If the odds are 0.999... then the odds are 1.0.
And anyway that's a bad analogy. Crossing the street probably gives me something like a 99.99994832% (made up number, but you get the point) chance of survival, which is of course worse than 99.99999...%, yet we make those decisions daily without thinking. Everybody's chance of living to tomorrow, while mostly very high, is worse than this. Which makes this a meaningless example.
Anonymous on May 16, 2009 12:55 PM@Ens on May 14, 2009 08:22 PM
"Not true! For the exact same reason that 1 + 1/2 + 1/4 + 1/8... doesn't equal infinity ..."
That series doesn't equal infinity. It equals 2. Because the infinite series 1/2 + 1/4 + 1/8... equals 1.
The simplest way to shows this is to write the series as a binary number: 0.111... There is 0 to the left of the binary point, so there are no units. To the right of the binary point is the digit 1, which represents 1/2 (i.e. base**-1). The next digit is 1, which represents 1/4 (base**-2). And so on. Forever.
So the binary (base-2) representation 0.111... (i.e. an infinite number of 1's) is exactly equivalent to the decimal (base-10) representation 0.999..., which has already been proven equal to 1.
You can do this in other bases, too. For example, in base-3, 1/3 is 0.1, 2/3 is 0.2, and it should be obvious that 0.222... is exactly equal to 1.
It's not the computer that has trouble - it's the programmer or the language. Try using scheme, which often implements precise arithmetic.
Ted on May 16, 2009 6:26 PMYou could have at least used an example where people died. I.E. the Patriot missle in the Gulf War.
TraumaPony on May 16, 2009 7:26 PMi see.. any program as only a certain logic error or a bug.
http/it.alonearea.com
AloneArea.com on May 16, 2009 9:00 PMtry this : http://www24.wolframalpha.com/input/?i=399999999999999-399999999999998
adinochestva on May 17, 2009 12:10 AM"I've accepted that 0.999... = 1
but I'm wondering what number would be "just" less than one to the infinitely-small number place?"
There is no such number, because for any number not equal to one, there is an infinite number of other numbers in between this number and one.
The problem with it is that the human brain is not able to grok infinity. Similar to most people not being able to grok pointers (ie. abstracted indirections). But while you can learn anything about memory, addressing and data storage to finally build a mental image of pointers and really understand them, who can say that he is able to build a mental image of infinity? Your wording is quite correct: The only way is to "accept" it by mathematical proof.
As this thread shows, there are a lot of people with the attitude "It can't be what I'm not able to understand".
Quoting Wikipedia: "Any integer less than or equal to 2^24 can be exactly represented in the single precision format, and any integer less than or equal to 2^53 can be exactly represented in the double precision format."
So Google could easily solve this problem by using double precision floats or by using 64-bit ints when integrers are used in calculations.
Alex on May 17, 2009 10:05 AM"Young man, in mathematics you donít understand things. You just get used to them." ó John von Neumann as quoted in The Dancing Wu Li Masters
:)
Read this for some good information about the hardware, the software, and how floating point can be used to great effect in the superior D Programming Language:
http://www.digitalmars.com/d/2.0/d-floating-point.html
anonymous on May 17, 2009 6:16 PMJeff, why do you insist on including some kind of image/clipart on *every* post you make? Occasionally they help make the post entertaining. More often than not it is simply annoying..
daved on May 18, 2009 6:13 AM@Eric Draven: The notion that 0.999... = 1 might be taught in grade school, but methods of the construction of the reals that that fact relies on can't be understood at that time by most children (or most adults, for that matter). And it's simply received wisdom until it can be understood.
But let's not turn this into a "People are smarter where I come from" thread. I don't think there's any point in trying to teach the *why* of this at an early age. The question about what the next number less than 1 is (except in the integers) reveals, I think, the futility of that. Denseness and uncountability are not intuitive, generally speaking, and they have to be internalized before you can really understand why 0.999... = 1.
It is a bit frustrating, though, that when Fact X violently contradicts someone's intuition, they almost invariably disbelieve X, rather than their intuition, even when (as in this case) there is no indication that their intuition should be at all reliable on the matter. (Viz. special relativity and the speed of light.) People who wouldn't presume to be able to run faster than Bolt or beat Kasparov at chess somehow instantly command deep mathematical resources when it comes to 0.999... = 1.
And, @Daniel Kaplun: It doesn't matter if Fact X comes from the mouth (digital though it may be) of a mathematician. If they don't want to accept it, they won't. And as I say, I don't think you can explain it adequately to most eighth-graders. At best, you can assert it before they "know" better.
Brian Tung on May 18, 2009 4:04 PM@Ed:
I think you misread my comment. I was pointing out that the image didn't need to be infinitely wrong for the same reason the infinite series I described is not infinity (it is, in fact, 2, as you described).
Ens on May 18, 2009 10:58 PM@J. Stoever
You'd fit right in with the ancient Greeks. They thought the idea of irrational numbers to be heresy. =)
Bill on May 20, 2009 12:00 AM@Darren
"The correct mathematical explanation is that 0.99999... (zero point nine recurring) approaches 1. Any pure mathematician (probably not many read Coding Horror...) would surely agree."
Surely would not :)
Notation 0,(9) means infinite sum (9/10^n), which doesnt approach 1. It is just equal 1. Belive me or get back to books and read about geometric progression ;p
For the same reason 0,(3) = 1/3 with stress to "="
regards
@Darren
"The correct mathematical explanation is that 0.99999... (zero point nine recurring) approaches 1. Any pure mathematician (probably not many read Coding Horror...) would surely agree."
Surely would not :)
Notation 0,(9) means infinite sum (9/10^n), which doesnt approach 1. It is just equal 1. Belive me or get back to books and read about geometric progression ;p
For the same reason 0,(3) = 1/3 with stress to "="
regards
There are better ways for computers to represent numbers, but just because something is better doesn't mean it will happen. See this paper on 'quote notation' http://dx.doi.org/10.1137/0208011.
Also, note that the paper is from 1979. That there's essentially no chance of this technique ever being adopted is a testament to the power of standards organizations.
Norm on May 20, 2009 8:56 AMYou should try Mathematica, it makes my computer very good at math.
Anonymous on May 21, 2009 4:06 AMWhy .999999... equals 1
if x = .99999999...
then 10x = 9.999999999....
now subtract each side,
10x - x = 9x
9.999... - 0.999... = 9
9x = 9
x = 1
thus .999999... = 1
The amount of comments in this post really testifies to how fundemental and occasionally confusing this subject is.
Qua on May 24, 2009 4:47 AM.99999999.... is 1 - an infinitesimal value.
The difference is meaningless unless you are dealing with infinities, then it becomes quite important.
As at least one other person has noted, the Ariane 5 explosion was NOT due a programming error.
It was the result of the decision to reuse a component from an Ariane 4 rocket. The Ariane 5 had peformance specs outside the range of what the component was designed to handle.
BOOM.
Matthew Sullivan on June 4, 2009 12:41 PMWolfram Alpha isn't sure:
Try this query and then click in the search box and press enter a few times.
http://www58.wolframalpha.com/input/?i=((10^5092107)-1)-((10^5092107)-2)
After a while, it'll get the answer wrong.
Alex on June 5, 2009 7:12 AM".99999999.... is 1 - an infinitesimal value.
The difference is meaningless unless you are dealing with infinities, then it becomes quite important."
no, the are *no* infeinitesimals in the Real numbers. as others have said you can can extend the reals to contain infinitesimals e.g. surreal numbers, but generally we don't have any use for these.
The Real numbers are strictly defined such that 0.(9) = 1 , not close to, not approaches, but isa exactly equalt to.
jk on June 17, 2009 2:22 AMProof of 0.99999... = 1
1 = 3/3 = 3 * (1/3) = 3 * (0.333333...) = 0.99999....
Hence, 1 = 0.999999....
QED
Kebabbert on August 4, 2009 3:12 AMHi, great site and comments.
I hope still develop this type of topics.
Salut to all, from chile.
phantomcl on August 10, 2009 4:02 PM@Darren - The correct mathematical explanation is that 0.99999... (zero point nine recurring) approaches 1
No - sequence .9, .99, .999, ... approaches 1 [by cauchy's epsilon delta definition] or you can see it is a cauchy sequence (numbers get arbitrarily close to each other) and every cauchy sequence has a limit in real numbers as real numbers are complete. In fact real numbers are defined as complete ordered (has <) field (has +, x)!
but .9999... with infinite 9s is indeed equal to 1, as that would be the limit of the sequence above and limit is unique. (you can prove that very easily yourself using ephsilon delta definition again.)
you can see it is a cauchy sequence (numbers get arbitrarily close to each other) and every cauchy sequence has a limit in real numbers as real numbers are complete.
links of london on August 26, 2009 1:14 AMno, the are *no* infeinitesimals in the Real numbers. as others have said you can can extend the reals to contain infinitesimals e.g. surreal numbers, but generally we don't have any use for these.
links of london on August 26, 2009 1:14 AMAbercrombie & Fitch on Sale, Hoodies, Jeans, T-Shirts, Pants, Polos abercrombie and fitch abercrombie fitch abercrombie cheap abercrombie fitch Abercrombie Men Tee abercrombie womens polos Abercrombie & Fitch Men, women, and children's clothing
abercrombie and fitch on August 28, 2009 12:35 AMTiffany Jewellery barely 2-year-old result called Iridesse is set to the more Tiffany Key Rings South Coast Plaza setting was the jeweler’s supreme tome branch stockTiffany Bracelets diamonds are about more than absolute condition, cut and beauty - they are one of our diamonds underscores.Tiffany Sets reputation as a world premier jeweler synonymous with diamonds of the finest feature,” added Bennett.
tiffany jewellery on August 28, 2009 2:43 AMNobody can ignore the existence of Christian Louboutin shoes in the fashion world. And what makes Christian Louboutin shoes so remarkable? Its exquisite quality, fine craftsmanship, sexy high heels, quirky designs and of course the red outsole known as the symbol of Christian Louboutin shoes.
christian louboutin on August 30, 2009 8:38 AMThen you will know what kind of is most suitable for you. http://linkslondon.blogsarena.com/Here are some tips for you to choose and match jewelries. Hope to have some assistance. Great attention should be paid to the coordination of the jewelries you chose to your face,http://linkslondon.blogsarena.com/ complexion, temperament, hairstyle, etc. so that you can obtain the most suitable jewelries. The key rule is your jewels can’t be in common with nor be completely different from your face shapehttp://linkslondon.blogsarena.com/ A triangle face is similar to a heart shape, but with corners angles
links on October 9, 2009 2:24 AMThe amount of comments in this post really testifies to how fundemental and occasionally confusing this subject is
iç giyim on October 13, 2009 12:32 AMVery cool! Congrats on the pairing.
ed hardy clothing on October 22, 2009 8:09 PMThanks for your information, i have read it, very good!
Very cool! Congrats on the pairing.
street lamps on October 24, 2009 1:46 AMlouis vuitton
[url=http://www.flashreplica.com]louis vuitton[/url]
fghjjhjjhjh on October 28, 2009 1:11 AM@JMW
Macintosh:~ gabornagy$ python
Python 2.6.1 (r261:67515, Jul 7 2009, 23:51:51)
[GCC 4.2.1 (Apple Inc. build 5646)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from decimal import Decimal
>>> Decimal("1")/Decimal("3")*Decimal('1000000000000000000000000000000')-Decimal('333333333333333333333333333333')
Decimal('-33')
>>>
@Alex
Macintosh:~ gabornagy$ bc -l
bc 1.06
Copyright 1991-1994, 1997, 1998, 2000 Free Software Foundation, Inc.
This is free software with ABSOLUTELY NO WARRANTY.
For details type `warranty'.
1/3*1000000-333333
.33333333333333000000
you can see it is a cauchy sequence (numbers get arbitrarily close to each other) and every cauchy sequence has a limit in real numbers as real numbers are complete.
bed on November 2, 2009 2:23 PMBing.com calculte it right
http://www.bing.com/search?q=399999999999999+-+399999999999998
I can design one calculator, very interesting.=0 is right.
valves manufacturer on November 3, 2009 4:22 PMwhy google can count =0? Does google not nicety? google is a search, not a calucator.
ball valves on November 3, 2009 4:25 PMHow beautiful picture that with zeros1
Coagulant on November 4, 2009 12:50 AMI can't understand.
Water treatment on November 4, 2009 12:55 AMvery good, thanks very much, I had read this.
butterfly valves on November 9, 2009 11:00 PM| Content (c) 2009 Jeff Atwood. Logo image used with permission of the author. (c) 1993 Steven C. McConnell. All Rights Reserved. |