0

I'm writing a program, where I have to rotate o point. But something in calculations isn't right.

That's function to rotate (Y-axis):

point3 rotY(point3 a, float angle){
    float x,z;
    z=a.z*cos(angle)-a.x*sin(angle);
    x=a.z*sin(angle)+a.x*cos(angle);
    a.z=z;
    a.x=x;
    return a;
}

That's point3 structure:

struct point3{
float x,y,z;
point3(){
    x=y=z=0.0f;
}
point3(float a,float b,float c){
    x=a;y=b;z=c;
}
};

Calling code:

point3 a(0.0f,l,0.0f);
    a=rotX(a,S->angle*rad);
    std::vector <point3> pocz(S->amount);
    for(int i=0;i<S->amount;i++)
        pocz[i]=rotY(a,(i*(360.0f/S->amount))*rad);

This (i*(360.0f/S->amount))*rad is rotation as on this pictureenter image description here

I know that for expample when a.x=0.0f, a.y=2.36880779 and a.z=2.36880779 and i want to rotate it by 180 degrees this function will return a.x=-2.07087751e-007, a.y=2.36880779 and a.z=-2.36880779.

But it should return a.x=0.0, a.y=2.36880779 and a.z=-2.36880779.

What can be wrong here?

Antua
  • 185
  • 9
  • Can you give us the call to rotY ? – Vincent Apr 29 '13 at 08:44
  • 3
    If you mean the `-2.07087751e-007` vs `0`, there's nothing wrong. `sin` and `cos` of floating point numbers cannot produce exact results. – kennytm Apr 29 '13 at 08:45
  • This is just a normal rounding error when it comes to floating and double point precision numbers. – Nomad101 Apr 29 '13 at 08:46
  • 3
    [_What Every Computer Scientist Should Know About Floating-Point Arithmetic_](http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html) – masoud Apr 29 '13 at 08:47
  • 1
    It looks right. You are getting a very small number for x, which is probably the result of algorithmic precision of cos and sin, plus general floating point precision. – juanchopanza Apr 29 '13 at 08:48
  • 1
    Do not reinvent the wheel : Boost contain some really cool libraries for space transformations. For example : http://www.boost.org/doc/libs/1_41_0/libs/math/doc/quaternion/html/ – lucasg Apr 29 '13 at 08:55
  • 1
    Sin & Cos are most likely implemented correctly, but the _argument_ can't possibly be a true multiple of 2*pi. See the possible duplicate. – Aki Suihkonen Apr 29 '13 at 09:03
  • Why 2*pi? Isn't pi=180 degrees? How this `(i*(360.0f/S->amount))*rad` looks like to rotate `a` point like here. (that means each new point is like on the new picture – Antua Apr 29 '13 at 09:07
  • pi radians = 180 degrees, yes. But when discussing `sin` and `cos`, we usually talk about their period, which is 2*pi radians. – MSalters Apr 29 '13 at 09:13
  • Maybe it isn't. rad=3.14159265f/180.0f; – Antua Apr 29 '13 at 09:16

1 Answers1

3

Nothing wrong here : floating-point arithmetic is approximative (up to 6 digits). More info on the subject : http://support.microsoft.com/kb/125056

As stated by juanchopanza, you can switch to double : http://en.wikipedia.org/wiki/Double-precision_floating-point_format

lucasg
  • 10,734
  • 4
  • 35
  • 57
  • Wont if be wrong later (when i will use this coords for next transformations)? – Antua Apr 29 '13 at 08:48
  • @Antua well, these small difference can propagate and eventually cause big errors. It is up to you to handle this. You could start by doing everything in `double` instead of `float`. – juanchopanza Apr 29 '13 at 08:49
  • 3
    Disagree with the simple advice to use `double`. That's not exact either. Any algorithm with exponential accumulation of error will still blow up, only taking twice as long. If the error accumulation is just linear, the float version often is good enough. And usually the error accumulation is less than that, random rounding errors will cancel on average. – MSalters Apr 29 '13 at 09:08
  • 1
    @MSalters "random rounding errors will cancel on average": this is another way of saying that most of the time, you'll get more or less correct results (but for some particular data sets, your results will be completely wrong). This is why you can't really test floating point---you have to really understand what you are doing, and have the code reviewed by other people who also understand floating point arithmetic. – James Kanze Apr 29 '13 at 09:13
  • @MSalters : The OP didn't talked about integrating the rotations (even if I suspect him to do so). The most robust solution - and the most complex one too - to apply rotations is to use Quaternions (and there is a Boost lib for that). – lucasg Apr 29 '13 at 09:15
  • @JamesKanze: Oh, no surprise there. I just had to deal with code overflowing a buffer, since my octagon had 9 corners. Root cause was different code paths disagreeing on whether the length of an edge was 0.0. – MSalters Apr 29 '13 at 09:17