13,049,172 members (68,968 online)
alternative version

#### Stats

29.4K views
23 bookmarked
Posted 19 Feb 2008

# Some handy decimal functions for double

, 20 Feb 2008
 Rate this:
Rounding, decimal places, etc..

## Introduction

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.

## Using the code

The functions are straightforward and self-explaining. These functions depend on math.h (and math.h only).

`#include <span class="code-string">"math.h"</span>`

`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```

## Points of Interest

• Note 1: `GetDecimalPlaces()` is worth some explanation. In a loop, the `double` is 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 `double`s is tricky because the internal representation of a `double` is not exact. So, the comparison must allow certain margins of error. The margin is specified by `THRES`, which is set to 1-10.

## History

• First version: 20 Feb 2008.

## Share

 Hong Kong
I don't know anything about Lisp, Ruby, D, EJB and J++.

## You may also be interested in...

 First Prev Next
 Bug? AvidFan28-Jun-12 1:01 AvidFan 28-Jun-12 1:01
 Re: Bug? Larry Harding24-Jul-12 4:04 Larry Harding 24-Jul-12 4:04
 Floating Point Explorer Mike O'Neill26-Feb-08 13:59 Mike O'Neill 26-Feb-08 13:59
 Re: Floating Point Explorer S.C.Wong27-Feb-08 15:06 S.C.Wong 27-Feb-08 15:06
 Incidentally ... Mike O'Neill27-Feb-08 15:48 Mike O'Neill 27-Feb-08 15:48
 Last Visit: 31-Dec-99 18:00     Last Update: 25-Jul-17 0:14 Refresh 1

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Web02 | 2.8.170713.1 | Last Updated 20 Feb 2008