tags:

views:

147

answers:

3

Vincent answered Fast Arc Cos algorithm by suggesting this function.

float arccos(float x) 
{ 
    x = 1 - (x + 1); 
    return pi * x / 2; 
} 

The question is, why x = 1 - (x + 1) and not x = -x?

+4  A: 

It returns a different result only when (x + 1) causes a loss of precision, that is, x is many orders of magnitude larger or smaller than one.

But I don't think this is tricky or sleight of hand, I think it's just plain wrong.

cos(0) = 1 but f(1) = -pi/2
cos(pi/2) = 0 but f(0) = 0
cos(pi) = -1 but f(-1) = pi/2

where f(x) is Vincent's arccos implementation. All of them are off by pi/2, a linear approximation that gets at least these three points correct would be

g(x) = (1 - x) * pi / 2
Ben Voigt
I don't still get loss of precision part, could you please provide an example?
David Weng
@David, try `1.0 - (1.0 + 1e-16)` vs `-(1e-16)`
aaa
Take a look at the graph of [acos](http://www.mathworks.com/access/helpdesk/help/techdoc/ref/acos.gif) - a better linear approximation (based on the tangent line at x=0) would be `g(x) = pi/2 - x`, which is pretty accurate except when x is close to -1 or 1
BlueRaja - Danny Pflughoeft
@BlueRaja: I agree that simply connecting these three points isn't optimal (and neither does using the tangent line at x=0 minimize the mean-square error), just that it's the most trivial approximation that could possibly be useful. The original one given by Vincent definitely was not useful.
Ben Voigt
A: 

I don't see the details instantly, but think about what happens as x approaches 1 or -1 from either side, and consider roundoff error.

Charlie Martin
A: 

Addition causes that both numbers are normalized (in this case, relevant for x). IIRC, in Knuth's volume 2, in the chapter on floating-point arithmetic, you can even see an expression like x+0.

zvrba