Re: Trigonometric Problem, Particularly tan() Function
Re: Trigonometric Problem, Particularly tan() Function
- Subject: Re: Trigonometric Problem, Particularly tan() Function
- From: Bill Monk <email@hidden>
- Date: Sun, 13 Jul 2008 14:01:55 -0500
On Jul 13, 2008 10:30:27 -0300, Patrick Walker
<email@hidden> wrote:
float radians;
radians = ([entryField floatValue] * M_PI / 180);
[outField setFloatValue:tan(radians)];
tan() takes a double and returns a double. Your code above truncates
doubles three different ways - the input, the intermediate
calculation, and the result. Instead, try something like
double_t input = [inputField doubleValue];
double_t radians = input * pi / 180;
double_t output = tan(radians);
if /* output is "near" infinity */
[outputField setStringValue:@"INFINITY"];
else
[outputField setDoubleValue:output];
My other problems seems to be -2877334 itself.
This is happening because
float radians = 90 * M_PI / 180; // == 1.57079637, truncated from
1.5707963267948966
double result = tan(radians); // == -22877332.428856459 (with <math.>)
but you essentially do
float truncatedResult = tan(pi/2); // == -22877332, truncated from
-22877332.428856459
The question is are there any
other than the numerical method "math.h" versions?
Instead of <math.h>, you can use <fp.> along with the '-llibm'
compiler flag to get the IEEE trig functions. It won't fix the
truncation problem. But it does define "pi" (nice) and gives a
slightly different result
double result = tan(pi/2); // == 1.633123935319537e+16
just on the other side of infinity from the -22877332.428856459
obtained with <math.>. Both are "wrong" but surely "close enough"; at
any rate about the best you can hope for.
BTW the Mac OS X Numerics manual at
<http://developer.apple.com/documentation/Performance/Conceptual/
Mac_OSX_Numerics/Mac_OSX_Numerics.pdf> (see pages 2-8 and 9-35)
indicates this should return a proper IEEE +INFINITY (0x7F800000,
binary 01111111 10000000 00000000 00000000). Theoretically you should
then be able recognize those values and display text like "INFINITY"
to the user.
I say "theoretically" because, while it's supposed to work that way
(and I recall it did under OS8/8/7) it doesn't necessarily seem to
anymore, given Intel and who knows what else. At least that's what
I've seen - I asked a similar question about cos() a while back:
http://lists.apple.com/archives/xcode-users/2006/Jun/msg00453.html
This answer from one of the Apple numerics guys seems relevant:
...how come the results of cos( pi/2 ) don't agree with the
behavior documented in PowerPC Numerics, page 148? Am I doing
something else wrong? Googling, I see that some other math libs
(Java, for instance) document that one should -not- expect cos( pi/
2 ) to equal exactly zero. This is at variance with what PowerPC
Numerics says OS X does, however.
C) If the behavior documented in PowerPC Numerics doesn't actually
occur, what's the proper thing to do? The app has some fairly heavy
arithmetic going on, with the results displayed to the user both
graphically in text form. Should it round before drawing? Round
before displaying text? Both? What have others done in this situation?
M_PI_2 (converted to double) is only an approximation to pi/2. It
is actually (and approximately) 6.1e-17 smaller than pi/2. The next
higher value which a 64 bit IEEE number can represent is
approximately 1.6e-16 bigger than pi/2.
It turns out that in the neighborhood of pi/2, cos(x) can be very
closely approximated by this simple linear function:
cos(x) =~ pi/2 - x
(derivation available upon request)
Plugging M_PI_2 into this approximation to cos(x) yields the result
you report: 6.1e-17. Using nextafter() to find the next
representable number above M_PI_2 and calling cos() on that number
yields approximately -1.6e-16 (again predicted by the linear
approximation to cos(x)).
The answer you're getting is a more accurate answer than 0 would be.
This suggests that what you're seeing is because pi/2, not being
exactly expressible on a computer, is a slightly inaccurate argument
to tan(). The result is accurate for the binary representation of pi/
2, but that representation of pi/2 is, unavoidably, not a perfect
right angle.
Or, to paraphrase the last sentence in the quote above, the answer
you're getting (or will get, once you fix the truncation issues) is a
more accurate answer than "infinity" would be.
If the result "close enough" to infinity for your purposes, just
display "infinity" as text, or round it off to some reasonable number
of digits so the user can see it's "close enough." This is really no
different than what a printed trig table does - make the values look
nice once a certain threshold is passed.
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden