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…

Popularity: 2% [?]

Share and Enjoy:
  • Print
  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Mixx
  • Google Bookmarks
  • Blogplay

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

  • Recent Comments

  • Tags

    AACS Adobe Photoshop Elements 6 Apple Apple Lossless C++ C/C++ CNN Customer Service Dell Digikam DRM Firefox FLAC Fortune Fortune-Widget Fortune File Ghosts I-IV Giga-Byte Google Google Analytics Hack Internet Explorer Kernel Kubuntu Lingo Linksys SPA2102 Linux Mandriva Microsoft Nine Inch Nails OpenSuse Parody PC World Performance Perl Plugin Pre-Installed Linux Quote of the Day Restaurant Software Engineering Ubuntu VOIP Widget Wordpress YouTube
  • Stack Overflow

    Gravatar
    Jason Mock
    591r
    39
  •  

    February 2007
    S M T W T F S
    « Dec   Mar »
     123
    45678910
    11121314151617
    18192021222324
    25262728  
  • Archives

  • Categories

  • Books I'm Reading

    ISBN: 0385504225 ISBN: 020161622X ISBN: 0596100469 ISBN: 0321344758