[C++] strangle sin/cos accuracy problems

Started by
16 comments, last by Adam_42 14 years, 11 months ago
I've suddenly started getting really weird results with calls to the built-in sin/cos functions in my C++ program. Everything was working fine, but suddenly objects which rotate go all glitchy and weird. I've tracked down the issue to the following line, which the debugger clearly shows as sin() using single precision floats giving the wrong answer:
float sin_a = sin(angle);
With angle being -0.0017453292, it gives sin_a = 0.096280068. According to my pocket calculator, the correct answer is -0.001745328314. Not only is the result wrongly positive (!!) but it's about 55 times larger! Even if I just enter directly the following line and compile:
const float weird = sin(-0.78539819);
The debugger shows the result being -0.63439333, versus my calculator saying -0.7071068, still out by the first digit, surely worse than single precision floats can achieve. In this particular program, my co-developer reported precisely the same wrong results on their computer too. So when anything rotates in my program everything goes all jittery and displays at the wrong angle. Obviously it works fine in a new program, and I have an assembly snippet using the fsincos instruction that doesn't seem to suffer precision problems, and the double precision overloads for sin and cos seem OK. But something must be seriously amiss here. What could cause such serious inaccuracy errors? I've no idea what I might've done to cause this - compiler settings? FPU control flags (I'm not changing any)? Cosmic rays???
Construct (Free open-source game creator)
Advertisement
display glitches could be a radian<->degree mismatch. Did you step over the line in question in debug mode after a full rebuild? (Remember, when the debugger first breaks on that line, sin_a will be uninitialized, because it stops BEFORE executing the highlighted line)
Yes, I had stepped over the line, and the calculation is definitely in radians. Even the line with a hard-coded parameter came out wrong.
Construct (Free open-source game creator)
Quote:Original post by AshleysBrain
With angle being -0.0017453292 [...] it's about 55 times larger!

Quick observations:
- your angle is very small
- for small angles, the sine function is approximately like a straight line
- 180/pi = 57 =~ 55
Would you mind posting a small program that shows what you are doing?
#include <cmath>#include <iostream>int main() {  const float weird = sin(-0.78539819);  std::cout << weird << '\n'; // prints -0.707107, as it should}
I've ssen such weirdness before wich we eventually blamed on issues with the SSE registers on some windows xp 64 bit only. Try to write a small function that asses the result of a known calculation an see from what point it starts going wrong (easier said than done) How big is your program? On large codebases, a small mistake somewhere can cause very paranormal results at the other end, I have seen that quite a lot...
At a random guess, your (or rather your compiler's) sin() function is using some kind of lookup table in its calculations.

As the results are wrong after a while, that suggests something else has overwritten that lookup table, due to an array overrun or other similar bug. If you can find the table by stepping into the sin function (reading of disassembly may be required), then a memory watch breakpoint in the debugger should find you the culprit quickly.

If that's not possible then checking at which point in the program sin() starts misbehaving will tell you when it's been trashed, and you can start narrowing it down by moving the tests.

This may also be a good time to start using of an array template that does bounds checking in debug builds.
It's a 100,000+ line program so I can't easy post any of it, and it's Visual Studio 2008. I thought sin() and cos() mapped directly to the fsin and fcos x86 instructions? I am using a little bit of MMX/SSE, and assembly running on startup for CPUID etc, but I've tried turning it all off and it doesn't fix anything...
Construct (Free open-source game creator)
Try to reproduce the problem in a tiny program: It's your best shot at figuring out what the problem is and, even if you don't, you can post it for us to help.
Are you able to test your program on another computer or another OS, and see if this happens in the same way?

This topic is closed to new replies.

Advertisement