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…
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.
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.