Round a Float to # of Significant Digits Following The Decimal Point

Unfortunately, this next couple of weeks I get to do some development in C, and have ran into the always lovely issue of rounding a floating point number within a given # of significant digits. First, the need to do this usually stems from the fact that atof(char*) or strtof(char*,char**) return values one wouldn’t want/expect.

Example:

char* sValue = "20.4323";
float fValue = atof(sValue);
printf("%f", fValue);  //Debugger reports 20.4323006,  Prints 20.432301

Of course, this is only an issue if you are needing to store and perform math against this value, since [s]printf can easily clean up the value for display. Either way, I came across a nice helper function that would probably be useful for anyone who doesn’t have access to libraries with precision control (I.E. STL).

inline double fround(double n, unsigned d)
{
   return floor(n * pow(10., d) + .5) / pow(10., d);
}

Every day you learn something new, even if it is back to basics…

This entry was posted in Software Development and tagged . Bookmark the permalink.

2 Responses to Round a Float to # of Significant Digits Following The Decimal Point

  1. David A. Pimentel says:

    Actually, this is not quite correct assuming you want significant figures instead of decimal places. Your function rounds to a spcified number of places after the decimal point. A definition of significant figures (or digits) can be found at http://en.wikipedia.org/wiki/Significant_figures. To retain only a specified number of significant figures, the function should be:

    inline double fround(double n, unsigned d)
    {
      unsigned p;
      p = d - (unsigned)log10(n);
      return floor(n * pow(10., p) + .5) / pow(10., p);
    }

    Given fround(1703.12345689,6), the result will be 1703.12, whereas, your original function will return 1703.123157.

    Here is a simple test to verify the results:

    #include <stdio.h>
    #include <math.h>

    inline double fround1(double n, unsigned d)
    {
      return floor(n * pow(10., d) + .5) / pow(10., d);
    }

    inline double fround(double n, unsigned d)
    {
      unsigned p;
      p = d - (unsigned)log10(n);
      return floor(n * pow(10., p) + .5) / pow(10., p);
    }

    int main() {
      printf("old fround: %21.8fn", fround1(1703.12345689,6));
      printf("new fround: %21.8fn", fround (1703.12345689,6));
    }

    Cheers.

  2. Jason Mock says:

    Actually, your comment made me realize that I didn’t properly describe what it was that I had created. In my specific case, I didn’t care about the number of significant digits, I only cared about the number digits following the decimal point. So, I may even re-title the post since it is obviously incorrect. Thank you for pointing that out and not letting me lead others astray.

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="" highlight="">