999999999999999 - 999999999999997
google.com
google.com
1) It affects millions of people!
2) It affects large amounts of money!
3) It is a great example of a new or rare class of bug. Here's how you can avoid introducing similar bugs into your code! Here's how we can detect these things automatically! etc.
Here, the only thing that springs to mind is IEEE floating point being used internally by Google Calculator for some reason, which I find hard to believe. Where's the insight?
I think you still have a few orders of magnitude to go before that becomes a real problem.
You can do nice matrix and vector math entirely in 16.16 fixed point. It's not as fast as having a co-processor, but there was a time that those were not standard items.
Why in the fuck would you try to do financial math with anything but fixed-point or rational numbers?
EDIT: single-precision does behave this way:
-bash-3.2$ cat precision.c
#include <stdio.h>
int main() {
float f1 = 999999999999999;
float f2 = 999999999999997;
printf("%f\n", f1 - f2);
return 0;
}
-bash-3.2$ gcc precision.c
-bash-3.2$ ./a.out
0.000000
I am saying that if it's not consistent with single-precision across multiple inputs, there's probably code that looks at the numbers involved and decides what kind of numeric type to use to do the calculations. In this case, single-precision floating-point happens to be a bad choice.Second edit: replacing the 7 with a 6 still prints 0. The parent is right: something else is going on here. I like the theory espoused elsewhere in this discussion that it's a result of some truncation to avoid returning nonzero when the result should be zero.
ZorbaTHut (http://mandible.net) said:
it's 80-bit ieee floats internally, but there's some specialized code
to clamp it to zero when it looks like it ought to be zero.
as far as I know it should otherwise behave exactly like 80-bit ieee
(it wouldn't surprise me if the clamping code is being a little overzealous
in this case)The first thing that springs to my mind is that Google calculator is free, and more precision isn't.
Pretty sloppy to not even detect overflow on the input.
another one:
http://www.google.com/#q=999999999999999999+-+90000000000000...
These are unsigned integers, they could have been represented as integers in a 64 bit unsigned value, if the number of bits in the variable destined to hold the input is not enough and you keep on working as though there are that's overflow al right.
It should have simply thrown an error: operand too large.
I have a dark brown feeling that it won't be long before it does though :)
They use floats for everything, not ints.
edit: actually, it doesn't, the input above is 15 digits long.
It all boils down to what type you consider the entries have, opposed to what Google considers.
Check out: http://www.google.com/search?q=999999999999999+*+1 this overflows into the next integer as well.
http://www.bing.com/search?q=999999999999999999999999999+-+9...
http://www.cs.niu.edu/other/pentium.html
I remember taking the chip into Digital at the time. They replaced it for me.
http://www.stata.com/statalist/archive/2002-10/msg00290.html
They're not using single-precision floats either; with one 9 fewer in each number, everything's fine, but those numbers are way out of range for 32-bit IEEE floats.
Doesn't look like fixed-precision decimals, either: reduce the second number by 1 and you correctly get a difference of 3.
I think what's going on is more likely this: whoever implemented this wanted to avoid giving nonzero answers to calculations whose correct answer is zero, and therefore put in some sort of deliberate truncation somewhere. (It's not clear to me exactly what -- maybe every addition or subtraction that produces an answer much much smaller than its inputs gets clamped to 0, or something.)
I don't think the truncation is happening purely at the output stage: if I as it to do the original calculation and multiply the result by 100, e.g., I still get 0. (I had to write it like that because otherwise HN's asterisks-mean-italics hack scrambles it. Even though the supposedly matching asterisk is in a different paragraph. PG, if you're reading this, I'd love it if you were to change that behaviour.)
In other words, I think we're seeing an unfortunate effect of the same feature that makes it say that cos(2*atan(1)) is 0 rather than reporting it as about 6.123 x 10^-17 (the actual result in IEEE doubles).
http://www.wolframalpha.com/input/?i=999999999999999+-+99999...
One of the reasons Lisp is a nice language for math is its numbers behave more like true mathematical numbers than the approximations of numbers that are easy to implement in finite computer hardware. For instance, integers in Common Lisp can be almost arbitrarily large rather than being limited by the size of a machine word.3 And dividing two integers results in an exact ratio, not a truncated value. And since ratios are represented as pairs of arbitrarily sized integers, ratios can represent arbitrarily precise fractions.4
On the other hand, for high-performance numeric programming, you may be willing to trade the exactitude of rationals for the speed offered by using the hardware's underlying floating-point operations. So, Common Lisp also offers several types of floating-point numbers, which are mapped by the implementation to the appropriate hardware-supported floating-point representations.5 Floats are also used to represent the results of a computation whose true mathematical value would be an irrational number.
Finally, Common Lisp supports complex numbers--the numbers that result from doing things such as taking square roots and logarithms of negative numbers. The Common Lisp standard even goes so far as to specify the principal values and branch cuts for irrational and transcendental functions on the complex domain.
Still, support of strict read/write invariance of floating point numbers (e.g. as described in Burger&Dybvig 1996 and Clinger 1990) doesn't seem to spread widely outside CL/Scheme camp. Concept of exact/inexact numbers as well.
Interestingly, for pure decimal operations it seems some other floating point representation is used. For example, http://www.google.com/search?q=1.0+-+0.2+-+0.2+-+0.2+-+0.2+-... returns mathematically correct result of zero. If double precision were being used it should return the mathematically incorrect result of 0.0000000000000000555 because of floating point representations errors.
http://www.appscout.com/2007/10/excel_bug_exterminated.php
Imagine being the accountant who learned about this too late...
However, in this case, Google means to say 0.0 × 10^15, indicating two sig figs of accuracy. Google's mistake is probably that the internal notation used does not allow it to distinguish between "0" and "0.0 x 10^15", and so it does not report that the result is only accurate to two sig figs as it should.
So, if Google somehow reports the "zero" result in scientific notation with two sig figs, then it will be consistent with the rest of their calculator and clear that it may not be an accurate result.
[1] http://search.yahoo.com/search;_ylt=A0geu.i5PZNKqSoAurJXNyoA... [2] http://www.bing.com/search?q=999999999999999+-+9999999999999...
http://www.skrenta.com/2008/04/microsoft_bias_in_msn_search_...
>>> 999999999999999 - 999999999999997
2L >>> float(999999999999999999) - float(999999999999999997)
0.0 C:\>ruby --version
ruby 1.8.6 (2008-08-11 patchlevel 287) [i386-mswin32]
C:\>irb
irb(main):001:0> 999999999999999 - 999999999999997
=> 2
irb(main):002:0> 9999999999999999 - 9999999999999997
=> 2
irb(main):003:0> 999999999999999.0 - 999999999999997.0
=> 2.0
irb(main):004:0> 9999999999999999.1 - 9999999999999997.1
=> 2.0>> 999999999999999 - 999999999999997 == 2.0
Rebol 3:
>> 999999999999999 - 999999999999997 == 2
The HP35 scientific calculator also give 0 as an answer.
wierd.
Sadly, it no longer works...
Also, http://www.wolframalpha.com/input/?i=infinity+-+(infinity+-+...
If nothing else, Wolfram Alpha is useful for math. I'm impressed that it understood my syntax for limits that I made up on the spot, first try.
For example, a while back a man got a bill for $35 billion ... that wouldn't happen with more intelligence built into routines. (OUR minds look at 999...999 and 999...997 and see quickly what can be eliminated.)
bash-3.1$ echo "(999999999999999 - 999999999999997)" | bc 2
I don't go on 4chan often - once or twice a year at most - but when I do, it's to get that completely random mix of things all at once. Every time, I come away with 3-4 things I didn't know/hadn't thought of before. This was one of the things I found this time.
I run a webcam site and over the years we've had some pretty weird stuff happening there and I really wished I had not seen any of that.
Edit: Apparently rms knows how; see his comment.
When I read those sentences I didn't even come close to thinking about underage girls, girls covered in fecal matter, or underaged girls covered in fecal matter. ;)
But I appreciate the pointer and I've filed it for future reference.
One thing though, my 'vivid imagination' really comes in to its own while reading books, I literally see the scene in front of me as though completely immersed in it.
I wrote an essay about how this widespread desensitization will affect society and culture. It'll be interesting to see the world in twenty years.
My new essays are all on Facebook at the moment.
But if you're not a programmer you don't know a float from a double, and it just looks so neat and funny that google screwed up.
And because it's so funny it showed up on 4Chan, then on reddit and now here too.
Perhaps it's not a unique case - icey's link explained the cause, which incidentally I hadn't known before posting this - but it's still one that's perhaps worth a conversation for some people.