sin, cos, tan and rounding error

前端 未结 9 616
执念已碎
执念已碎 2020-12-06 14:09

I\'m doing some trigonometry calculations in C/C++ and am running into problems with rounding errors. For example, on my Linux system:

#include 

        
相关标签:
9条回答
  • 2020-12-06 14:36

    An IEEE double stores 52 bits of mantissa, with the "implicit leading one" forming a 53 bit number. An error in the bottom bit of a result therefore makes up about 1/2^53 of the scale of the numbers. Your output is of the same order as 1.0, so that comes out to just about exactly one part in 10^16 (because 53*log(2)/log(10) == 15.9).

    So yes. This is about the limit of the precision you can expect. I'm not sure what the ULP technique you're using is, but I suspect you're applying it wrong.

    0 讨论(0)
  • 2020-12-06 14:36

    Unless your program requires significant digits out to the 16th decimal place or more, you probably can do the rounding manually. From my experience programming games we always rounded our decimals to a tolerable significant digit. For example:

    #include <math.h>
    #include <stdio.h>
    #include <stdlib.h>
    
    #define HALF 0.5
    #define GREATER_EQUAL_HALF(X) (X) >= HALF
    
    double const M_PI = 2 * acos(0.0);
    
    double round(double val, unsigned  places = 1) 
    {
        val = val * pow(10.0f, (float)places);
        long longval = (long)val;
        if ( GREATER_EQUAL_HALF(val - longval) ) {
           return ceil(val) / pow(10.0f, (float)places);
        } else {
          return floor(val) / pow(10.0f, (float)places);
        }
    }
    
    int main() 
    {
        printf("\nValue %lf", round(sin(M_PI), 10));
        return 0;
    }
    
    0 讨论(0)
  • 2020-12-06 14:41

    @Josh Kelley - ok serious answer.
    In general you should never compare the results of any operation involving floats or doubles with each other.

    The only exceptions is assignment.
    float a=10.0;
    float b=10.0;
    then a==b

    Otherwise you always have to write some function like bool IsClose(float a,float b, float error) to allow you to check if two numbers are within 'error' of each other.
    Remember to also check signs/use fabs - you could have -1.224647e-16

    0 讨论(0)
提交回复
热议问题