Hot!Wrong cos() result

Page: 12 > Showing page 1 of 2
Author
Igor Kocman
New Member
  • Total Posts : 6
  • Reward points : 0
  • Joined: 2014/04/15 15:49:14
  • Location: 0
  • Status: offline
2018/02/03 11:59:07 (permalink)
0

Wrong cos() result

Hi,
 
I have a very strange problem:
 

long lineCos(float degree, long len)
{
    volatile float c1,c2;
    c1 = degree*3.141/180.0;
    c2 = cos(c1);
    return (c2*len);
}


And the return value is wrong.
For example when the degree=0 then c2=1.25 instead 1.0.
A spend many hours on this problem. Any idea?
 
Thank in advance.
Igor
 
#1

22 Replies Related Threads

    1and0
    Access is Denied
    • Total Posts : 7495
    • Reward points : 0
    • Joined: 2007/05/06 12:03:20
    • Location: Harry's Gray Matter
    • Status: offline
    Re: Wrong cos() result 2018/02/03 12:37:09 (permalink)
    #2
    Igor Kocman
    New Member
    • Total Posts : 6
    • Reward points : 0
    • Joined: 2014/04/15 15:49:14
    • Location: 0
    • Status: offline
    Re: Wrong cos() result 2018/02/03 13:30:32 (permalink)
    0
    Thany you, but i think this is not the case.
     
    I use XC32 1.32 and PIC32MX370. Legacy libc.
    Interesting is that 2 weeks this piece of code works perfectly and today suddenly with wrong result. I made no changes at all, I just run the program and see that the line is too long. Of course is too long while cos(0) is more than 1.
     
    I really have no idea.
    #3
    Igor Kocman
    New Member
    • Total Posts : 6
    • Reward points : 0
    • Joined: 2014/04/15 15:49:14
    • Location: 0
    • Status: offline
    Re: Wrong cos() result 2018/02/03 13:35:25 (permalink)
    0
    And if I do this:
     
    long lineCos(float degree, long len)
    {
        volatile float c1,c2;
        degree = 0;
        c1 = degree*3.141/180.0;
        c2 = cos(c1);
        return (c2*len);
    }
     
    Then teh result is 1.0
    wtf???
    #4
    bblessing
    Super Member
    • Total Posts : 600
    • Reward points : 0
    • Joined: 2008/12/04 06:44:21
    • Location: Cincinnati, OH
    • Status: online
    Re: Wrong cos() result 2018/02/03 14:30:24 (permalink)
    0
    Would it be worth changing course and using a lookup table for cos? Should be a lot faster.
    #5
    Bob White
    Super Member
    • Total Posts : 159
    • Reward points : 0
    • Joined: 2010/11/06 19:52:38
    • Location: Denver, Colorado
    • Status: offline
    Re: Wrong cos() result 2018/02/03 14:52:56 (permalink)
    -1 (1)
    Igor Kocman
     
    long lineCos(float degree, long len)
    {
       volatile float c1,c2;
        c1 = degree*3.141/180.0;
       c2 = cos(c1);
       return (c2*len);
    }



    What do you expect the result of (c2*len) to be?  You are multiplying a float by a long.  You need to check the type promotion rules.  len would be converted to float and the returned value would be a float.  I think your problem lies in the type conversion.
     
    #6
    Igor Kocman
    New Member
    • Total Posts : 6
    • Reward points : 0
    • Joined: 2014/04/15 15:49:14
    • Location: 0
    • Status: offline
    Re: Wrong cos() result 2018/02/03 15:45:26 (permalink)
    0
    The problem is in c2 wich is cos(c1).  c1,c2 and degree are float but the result of cos(c1) is wrong!
    This is the problem.
    #7
    Gort2015
    Klaatu Barada Nikto
    • Total Posts : 1916
    • Reward points : 0
    • Joined: 2015/04/30 10:49:57
    • Location: 0
    • Status: online
    Re: Wrong cos() result 2018/02/03 16:11:24 (permalink)
    0
    Try double.

    MPLab X playing up, bug in your code? Nevermind, Star Trek:Discovery will be with us soon.
    https://www.youtube.com/watch?v=Iu1qa8N2ID0
    + ST:Continues, "What Ships are Made for", Q's back.
    #8
    andersm
    Super Member
    • Total Posts : 2333
    • Reward points : 0
    • Joined: 2012/10/07 14:57:44
    • Location: 0
    • Status: offline
    Re: Wrong cos() result 2018/02/04 02:08:30 (permalink)
    +1 (1)
    Please post a full reproducible example, complete with build configuration.
    #9
    Igor Kocman
    New Member
    • Total Posts : 6
    • Reward points : 0
    • Joined: 2014/04/15 15:49:14
    • Location: 0
    • Status: offline
    Re: Wrong cos() result 2018/02/04 02:20:08 (permalink)
    0
    I try already but with no success.
    #10
    Gort2015
    Klaatu Barada Nikto
    • Total Posts : 1916
    • Reward points : 0
    • Joined: 2015/04/30 10:49:57
    • Location: 0
    • Status: online
    Re: Wrong cos() result 2018/02/04 07:22:47 (permalink)
    0
    There is a problem with floating point, they are approximations, the more bits used, the better the apx.
    That is all libraries and maths co-proccessors including calculators.
     
    Another reason why a lookup table was suggested.
     
    If you need accuracy, a specialised library would be needed but I doubt you would need that.

    MPLab X playing up, bug in your code? Nevermind, Star Trek:Discovery will be with us soon.
    https://www.youtube.com/watch?v=Iu1qa8N2ID0
    + ST:Continues, "What Ships are Made for", Q's back.
    #11
    Gort2015
    Klaatu Barada Nikto
    • Total Posts : 1916
    • Reward points : 0
    • Joined: 2015/04/30 10:49:57
    • Location: 0
    • Status: online
    Re: Wrong cos() result 2018/02/04 07:25:52 (permalink)
    0
    Look up Q1.5 for better expanations.
    Some chips will have 512bits.
     

    MPLab X playing up, bug in your code? Nevermind, Star Trek:Discovery will be with us soon.
    https://www.youtube.com/watch?v=Iu1qa8N2ID0
    + ST:Continues, "What Ships are Made for", Q's back.
    #12
    Gort2015
    Klaatu Barada Nikto
    • Total Posts : 1916
    • Reward points : 0
    • Joined: 2015/04/30 10:49:57
    • Location: 0
    • Status: online
    Re: Wrong cos() result 2018/02/04 07:59:46 (permalink)
    -1 (1)
    Try:
    long lineCos(double degree, long len)
    {
        static double PI=22.0/7; //calculate once
        double c1,c2;

        c1 = degree*PI/180.0;
        c2 = cos(c1);
        return (c2*len);
    }


    MPLab X playing up, bug in your code? Nevermind, Star Trek:Discovery will be with us soon.
    https://www.youtube.com/watch?v=Iu1qa8N2ID0
    + ST:Continues, "What Ships are Made for", Q's back.
    #13
    1and0
    Access is Denied
    • Total Posts : 7495
    • Reward points : 0
    • Joined: 2007/05/06 12:03:20
    • Location: Harry's Gray Matter
    • Status: offline
    Re: Wrong cos() result 2018/02/04 08:51:39 (permalink)
    +1 (1)
    Gort2015
        static double PI=22.0/7; //calculate once

    That is a very bad approximation for PI as it's good to only 2 decimal digits.  Try
    #define PI   3.1415926535897932384626433832795028841971693993751058209749445923078164 06286 
    ;)  and this constant is probably already defined in a XC32 header file, like in XC16.
     
     
    #14
    moser
    Super Member
    • Total Posts : 305
    • Reward points : 0
    • Joined: 2015/06/16 02:53:47
    • Location: 0
    • Status: online
    Re: Wrong cos() result 2018/02/05 02:44:40 (permalink)
    +1 (1)
    #include <math.h>

    There is already a constant defined: 
    #define M_PI 3.14159265358979323846 /* pi */

    Then just put a bracket around those things which can be calculated in advance, so this allows the compiler to do it's job and optimize it:
    c1 = degree*(M_PI/180.0);

     
    But I'm very sure that is not causing the problems. Floating point arithmetic involving a 0.0 is exact! So cos(0.0) should not be anywhere far from 1.0, or otherwise the math lib is broken.
     
    Microchip has a long and sad history of failing with math and printf functions. In addition to that they support compiler flags which change the size of the double type (with -fno-short-double). However, their libraries often failed to use the correct version, and tried to call a 64bit double implementation of the function with 32 bit parameters and such things. I would expect that this is one of those problems.
     
    Maybe you should just use a newer version of the compiler. XC32 1.32 is quite old.
    Make sure you are definitely using legacy lib.
    And don't forget to include <math.h>.
     
    Then I have also a question: How did you find out that for degree=0 you get c2=1.25? Did you check with the debugger or did you print out that value?
    post edited by moser - 2018/02/05 06:09:41
    #15
    crosland
    Super Member
    • Total Posts : 1142
    • Reward points : 0
    • Joined: 2005/05/10 10:55:05
    • Location: Bucks, UK
    • Status: offline
    Re: Wrong cos() result 2018/02/05 06:26:55 (permalink)
    0
    Igor Kocman
    And if I do this:
     
    long lineCos(float degree, long len)
    {
       volatile float c1,c2;
        degree = 0;
       c1 = degree*3.141/180.0;
       c2 = cos(c1);
       return (c2*len);
    }
     
    Then teh result is 1.0
    wtf???


     
    Your return type is long, so the result cannot be 1.0, which is a float or double. It can only be 1, or some other integer value.
    #16
    Gort2015
    Klaatu Barada Nikto
    • Total Posts : 1916
    • Reward points : 0
    • Joined: 2015/04/30 10:49:57
    • Location: 0
    • Status: online
    Re: Wrong cos() result 2018/02/05 06:35:07 (permalink)
    0
    I use a look table that I created in Excel.
     
    The table only needs to be a quarter of the size. i.e. 0-89 degrees when stored on chip.
    You can get the other 3 quadrants and sin and cos from the same table.
    Radians, degrees and Q1.5 numbers.
     
    You are never going to match the speed of a lookup table when calculating sin and cos.
     
    Step=45,  Electrical Angle 15.8203125, Radian 0.27612, Sine 0.27262, Cosine 0.96212
    Duty Cycle 27.26213554, Rounded DC 27, Q15 8933
     

    MPLab X playing up, bug in your code? Nevermind, Star Trek:Discovery will be with us soon.
    https://www.youtube.com/watch?v=Iu1qa8N2ID0
    + ST:Continues, "What Ships are Made for", Q's back.
    #17
    1and0
    Access is Denied
    • Total Posts : 7495
    • Reward points : 0
    • Joined: 2007/05/06 12:03:20
    • Location: Harry's Gray Matter
    • Status: offline
    Re: Wrong cos() result 2018/02/05 06:44:16 (permalink)
    0
    crosland
    Your return type is long, so the result cannot be 1.0, which is a float or double. It can only be 1, or some other integer value.

    OP said c2 = 1.0 when degree=0 is assigned in the function, but c2 > 1.0 when degree is passed in a 0.
     
    #18
    1and0
    Access is Denied
    • Total Posts : 7495
    • Reward points : 0
    • Joined: 2007/05/06 12:03:20
    • Location: Harry's Gray Matter
    • Status: offline
    Re: Wrong cos() result 2018/02/05 06:49:44 (permalink)
    0
    Gort2015
    You are never going to match the speed of a lookup table when calculating sin and cos.

    We can agree on that, but the issue here might be a bug with the math library.
    #19
    davekw7x
    Entropy++
    • Total Posts : 1320
    • Reward points : 0
    • Joined: 2012/01/16 12:01:07
    • Location: Left Coast, USA
    • Status: offline
    Re: Wrong cos() result 2018/02/05 11:55:18 (permalink)
    +1 (1)
    Igor Kocman
    The problem is in c2 wich is cos(c1).  c1,c2 and degree are float but the result of cos(c1) is wrong!
    This is the problem.


    From the code that you posted, the only way that you can know the value of c2 is to look at an IDE display while debugging.
    Well...
    I can't look over your shoulder to see if I can understand and/or duplicate your problem.
     
    But...
    I know that, over the years, people have reported problems with xc32 math functions being very picky about how they are called and, more troublesome, how floating point values are displayed in the IDE if you don't do it right (or, in some cases, even if you do).
     
    So...
    To try to help you, I simply won't test anything with an IDE display or with the debugger.  I mean, even if I "got it right," you can't look over my shoulder to see how I did it.
     
    However...
    I'll run your function in production mode and show how I might use printf to test your function and its functionality.  My function is almost like yours, except for the instrumentation and the "slight" improvement in the value of pi that I use.  (Value of pi didn't make any fundamental difference, but I can't stand the thought of releasing code into the wild that uses poor approximations.)
     
    Note that...
    In my main() function I also printed out a little preamble, as I always do when starting a new project to remind me about some characteristics of the various XC32 types.   I called my function with the values of degree and len that you reported problems with, and some other values just to see if the function makes sense with other inputs.
     
    // #includes and local #defines go here.
    //
    //Configuration parameters are in a separate .c file in the project
    //

    // I'll call my function "foo" so it won't be confused with yours.
    long foo(float degree, long len)
    {
        volatile float c1, c2; // Don't need to be volatile, but I guess it doesn't hurt.
        //c1 = degree*3.141/180.0; // Not a very good approximation of pi
        c1 = degree * M_PI / 180.0; // M_PI is the value of pi defined in <math.h>
        printf("  In foo(%f, %ld):\r\n", degree, len);
        printf("    c1 = %f radians\r\n", c1);
        c2 = cos(c1);
        printf("    c2 = %f\r\n", c2);
        printf("    foo() returning %ld\r\n", (long)(c2*len));
        return (c2*len);
    }

    int main()
    {
        
        // Initialize clock, timers, uart, etc...
        init_system();
        
        printf("\r\nCompiled on %s at %s PST by XC32 version %d\r\n\r\n",
                __DATE__, __TIME__, __XC32_VERSION);
        printf("------------------------------------\r\n");
        printf("Sizes of integer data types:\r\n");
        printf("    sizeof(char)        = %d\r\n", sizeof(char));
        printf("    sizeof(short)       = %d\r\n", sizeof(short));
        printf("    sizeof(int)         = %d\r\n", sizeof(int));
        printf("    sizeof(long)        = %d\r\n", sizeof(long));
        printf("    sizeof(long long)   = %d\r\n\r\n", sizeof(long long));
        printf("Sizes of floating point data types:\r\n");
        printf("    sizeof(float)       = %d\r\n", sizeof(float));
        printf("    sizeof(double)      = %d\r\n", sizeof(double));
        printf("    sizeof(long double) = %d\r\n", sizeof(long double));
        printf("------------------------------------\r\n\r\n");
           
        float deg;
        long len;
        long result;
        int i;
        for (i = 0, deg = 0, len = 1; i < 2; i++, deg+=30,len+=123456788L) {
            printf("deg = %f\r\n", deg);
            printf("len = %ld = 0x%08lX, (float)len = %f\r\n", len, len, (float)len);
            printf("Calling foo(%f,%ld)\r\n", deg, len);
            result = foo(deg, len);
            printf("result = %ld = 0x%08lX\r\n\r\n", result, result);
        }

        // Other stuff...

    } // End of main()

     
    Output:
    Compiled on Feb  5 2018 at 09:07:06 PST by XC32 version 1440

    ------------------------------------
    Sizes of integer data types:
        sizeof(char)        = 1
        sizeof(short)       = 2
        sizeof(int)         = 4
        sizeof(long)        = 4
        sizeof(long long)   = 8

    Sizes of floating point data types:
        sizeof(float)       = 4
        sizeof(double)      = 4
        sizeof(long double) = 8
    ------------------------------------

    deg = 0.000000
    len = 1 = 0x00000001, (float)len = 1.000000
    Calling foo(0.000000,1)
      In foo(0.000000, 1):
        c1 = 0.000000 radians
        c2 = 1.000000
        foo() returning 1
    result = 1 = 0x00000001

    deg = 30.000000
    len = 123456789 = 0x075BCD15, (float)len = 123456780.000000
    Calling foo(30.000000,123456789)
      In foo(30.000000, 123456789):
        c1 = 0.523599 radians
        c2 = 0.866025
        foo() returning 106916720
    result = 106916720 = 0x065F6B70


    Tested on my PIC32MX470 Curiosity board with XC32 free version 1.44, Optimization level 1.  Legacy libc selected in XC32 Global Options in MPLABX version 4.10.
     
    Bottom line: Math library, at least as far as the two values that I fed to cos(), seems to be OK.
     
    Regards,

    Dave
    post edited by davekw7x - 2018/02/05 11:57:29

    Sometimes I just can't help myself...
    #20
    Page: 12 > Showing page 1 of 2
    Jump to:
    © 2018 APG vNext Commercial Version 4.5