I use the functions in math.h a lot. But, some functions are missing, so I wrote my own. They are simple functions dealing with decimal places. Nothing big and fancy. But they can be handy sometimes.
The functions are straightforward and self-explaining. These functions depend on math.h (and math.h only).
#include "math.h"
Round() rounds a double to a certain number of decimal places. It is very similar to Excel's Round function.
// rounds a double variable to nPlaces decimal places double Round(double dbVal, int nPlaces /* = 0 */) { const double dbShift = pow(10.0, nPlaces); return floor(dbVal * dbShift + 0.5) / dbShift; }
GetDecimalPlaces() counts and returns the number of decimal places of a
double (refer to note 1).
// get the number of decimal places int GetDecimalPlaces(double dbVal) { static const int MAX_DP = 10; static const double THRES = pow(0.1, MAX_DP); if (dbVal == 0.0) return 0; int nDecimal = 0; while (dbVal - floor(dbVal) > THRES && nDecimal < MAX_DP) { dbVal *= 10.0; nDecimal++; } return nDecimal; }
GetFmtStr() makes a
printf()-style format string.
// get the number format string const char* GetFmtStr(char* szFmt, int nDecimal) { sprintf(szFmt, "%%.%dlf", nDecimal); return szFmt; }
Finally,
RoundUD() rounds up or rounds down a double to its nearest value in
dbUnit steps.
// round up/down to certain units double RoundUD(bool bRoundUp, double dbUnit, double dbVal) { static const int ROUND_DP = 10; double dbValInUnit = dbVal / dbUnit; dbValInUnit = Round(dbValInUnit, ROUND_DP); if (bRoundUp) // round up dbValInUnit = ceil(dbValInUnit); else // round down dbValInUnit = floor(dbValInUnit); return (dbValInUnit * dbUnit); }
You can test the functions above with the following code:
printf("rounding %lf d.p.=%d is %lf\n", 10.0, 1, Round(10.0, 1)); printf("rounding %lf d.p.=%d is %lf\n", 0.0, 0, Round(0.0, 1)); printf("rounding %lf d.p.=%d is %lf\n", 0.1, 1, Round(0.1, 1)); printf("rounding %lf d.p.=%d is %lf\n", 0.01, 1, Round(0.01, 1)); printf("rounding %lf d.p.=%d is %lf\n", 0.0123456, 0, Round(0.0123456, 0)); printf("rounding %lf d.p.=%d is %lf\n", 0.0123456, 1, Round(0.0123456, 1)); printf("rounding %lf d.p.=%d is %lf\n", 0.0123456, 2, Round(0.0123456, 2)); printf("rounding %lf d.p.=%d is %lf\n", 0.0123456, 6, Round(0.0123456, 6)); printf("rounding %lf d.p.=%d is %lf\n", -0.0123456, 6, Round(-0.0123456, 6)); printf("rounding %lf up unit=%lf is %lf\n", 0.0, 0.05, RoundUD(true, 0.05, 0.0)); printf("rounding %lf down unit=%lf is %lf\n", 0.0, 0.05, RoundUD(false, 0.05, 0.0)); printf("rounding %lf up unit=%lf is %lf\n", 0.01, 0.05, RoundUD(true, 0.05, 0.01)); printf("rounding %lf down unit=%lf is %lf\n", 0.01, 0.05, RoundUD(false, 0.05, 0.01)); printf("rounding %lf up unit=%lf is %lf\n", -0.01, 0.05, RoundUD(true, 0.05, -0.01)); printf("rounding %lf down unit=%lf is %lf\n", -0.01, 0.05, RoundUD(false, 0.05, -0.01)); printf("%lf has %d d.p.\n", 0.0, GetDecimalPlaces(0.0)); printf("%lf has %d d.p.\n", 10.0, GetDecimalPlaces(10.0)); printf("%lf has %d d.p.\n", -10.0, GetDecimalPlaces(-10.0)); printf("%lf has %d d.p.\n", 10.123, GetDecimalPlaces(10.123)); printf("%lf has %d d.p.\n", -10.123, GetDecimalPlaces(-10.123)); printf("%lf has %d d.p.\n", 10.01, GetDecimalPlaces(10.01)); printf("%lf has %d d.p.\n", -10.01, GetDecimalPlaces(-10.01)); char szFmt[32]; printf(GetFmtStr(szFmt, GetDecimalPlaces(0.0)), 0.0); printf("\n"); printf(GetFmtStr(szFmt, GetDecimalPlaces(10.0)), 10.0); printf("\n"); printf(GetFmtStr(szFmt, GetDecimalPlaces(10.010)), 10.010); printf("\n"); printf(GetFmtStr(szFmt, GetDecimalPlaces(-0.0345)), -0.0345); printf("\n");
The output will be something like:
rounding 10.000000 d.p.=1 is 10.000000 rounding 0.000000 d.p.=0 is 0.000000 rounding 0.100000 d.p.=1 is 0.100000 rounding 0.010000 d.p.=1 is 0.000000 rounding 0.012346 d.p.=0 is 0.000000 rounding 0.012346 d.p.=1 is 0.000000 rounding 0.012346 d.p.=2 is 0.010000 rounding 0.012346 d.p.=6 is 0.012346 rounding -0.012346 d.p.=6 is -0.012346 rounding 0.000000 up unit=0.050000 is 0.000000 rounding 0.000000 down unit=0.050000 is 0.000000 rounding 0.010000 up unit=0.050000 is 0.050000 rounding 0.010000 down unit=0.050000 is 0.000000 rounding -0.010000 up unit=0.050000 is 0.000000 rounding -0.010000 down unit=0.050000 is -0.050000 0.000000 has 0 d.p. 10.000000 has 0 d.p. -10.000000 has 0 d.p. 10.123000 has 3 d.p. -10.123000 has 3 d.p. 10.010000 has 2 d.p. -10.010000 has 2 d.p. 0 10 10.01 -0.0345
GetDecimalPlaces()is worth some explanation. In a loop, the
doubleis multiplied by 10 and then compared to its floor value (truncated value). If they are the same, it means we have exhausted the decimal places. Comparison between
doubles is tricky because the internal representation of a
doubleis not exact. So, the comparison must allow certain margins of error. The margin is specified by
THRES, which is set to 1-10.
General
News
Question
Answer
Joke
Rant
Admin