Velocity Reviews > Rounding a floating point number

Rounding a floating point number

user923005
Guest
Posts: n/a

 02-25-2008
On Feb 25, 2:18*am, jacob navia <(E-Mail Removed)> wrote:
> Hi
>
> "How can I round a number to x decimal places" ?
>
> This question keeps appearing. I would propose the following
> solution
>
> #include <float.h>
> #include <math.h>
>
> double roundto(double x, int digits)
> {
> * * * * int sgn=1;
>
> * * * * if (x == 0)
> * * * * * * * * return 0;
> * * * * if (digits > DBL_DIG)
> * * * * * * * * digits = DBL_DIG;
> * * * * else if (digits < 1)
> * * * * * * * * digits = 1;
>
> * * * * if(x < 0.0) {
> * * * * * * * * sgn = -sgn;
> * * * * * * * * x = -x;
> * * * * }
> * * * * double p = floorl(log10l(x));
> * * * * p--;
> * * * * p = digits-p;
> * * * * double pow10 = pow(10.0, p);
> * * * * return sgn*floor(x*pow10+0.5)/pow10;
>
> }
>
> long double roundtol(long double x, int digits)
> {
> * * * * int sgn=1;
>
> * * * * if (x == 0)
> * * * * * * * * return 0;
> * * * * if (digits > LDBL_DIG)
> * * * * * * * * digits = LDBL_DIG;
> * * * * else if (digits < 1)
> * * * * * * * * digits = 1;
>
> * * * * if(x < 0.0) {
> * * * * * * * * sgn = -sgn;
> * * * * * * * * x = -x;
> * * * * }
> * * * * long double p = floorl(log10l(x));
> * * * * p--;
> * * * * p = digits-p;
> * * * * long double pow10 = powl(10.0, p);
> * * * * return sgn*floorl(x*pow10+0.5)/pow10;}
>
> #include <stdio.h>
> int main(void)
> {
> * * * * double d = 1.7888889988996678;
> * * * * long double ld = 1.7888889988996678998877L;
>
> * * * * for (int i = 0; i<=DBL_DIG;i++) {
> * * * * * * * * printf("i=%d: %.15g\n",i,roundto(d,i));
> * * * * }
> * * * * printf("\n * * *1.7888889988996678\n");
> * * * * for (int i = 0; i<=LDBL_DIG;i++) {
> * * * * * * * * printf("i=%d: %.18Lg\n",i,roundtol(ld,i));
> * * * * }
> * * * * printf("\n * * *1.7888889988996678998877L\n");
> * * * * return 0;
>
> }
>
> --------------------------------------------------------------------
> I would propose it to add it to the FAQ.

This is the snippet's solution (which is very similar to yours):
/* round number n to d decimal points */
double fround(double n, unsigned d)
{
return floor(n * pow(10., d) + .5) / pow(10., d);
}

Of course, no solution is really going to be satisfying, as long as
the output format is floating point.
Another question is "What kind of rounding?" Do we want banker's
rounding or round to nearest or what?
Should we create a round function for each distinct floating point
type?

user923005
Guest
Posts: n/a

 02-25-2008
On Feb 25, 2:18*am, jacob navia <(E-Mail Removed)> wrote:
> Hi
>
> "How can I round a number to x decimal places" ?
>
> This question keeps appearing. I would propose the following
> solution
>
> #include <float.h>
> #include <math.h>
>
> double roundto(double x, int digits)
> {
> * * * * int sgn=1;
>
> * * * * if (x == 0)
> * * * * * * * * return 0;
> * * * * if (digits > DBL_DIG)
> * * * * * * * * digits = DBL_DIG;
> * * * * else if (digits < 1)
> * * * * * * * * digits = 1;
>
> * * * * if(x < 0.0) {
> * * * * * * * * sgn = -sgn;
> * * * * * * * * x = -x;
> * * * * }
> * * * * double p = floorl(log10l(x));
> * * * * p--;
> * * * * p = digits-p;
> * * * * double pow10 = pow(10.0, p);
> * * * * return sgn*floor(x*pow10+0.5)/pow10;
>
> }
>
> long double roundtol(long double x, int digits)
> {
> * * * * int sgn=1;
>
> * * * * if (x == 0)
> * * * * * * * * return 0;
> * * * * if (digits > LDBL_DIG)
> * * * * * * * * digits = LDBL_DIG;
> * * * * else if (digits < 1)
> * * * * * * * * digits = 1;
>
> * * * * if(x < 0.0) {
> * * * * * * * * sgn = -sgn;
> * * * * * * * * x = -x;
> * * * * }
> * * * * long double p = floorl(log10l(x));
> * * * * p--;
> * * * * p = digits-p;
> * * * * long double pow10 = powl(10.0, p);
> * * * * return sgn*floorl(x*pow10+0.5)/pow10;}
>
> #include <stdio.h>
> int main(void)
> {
> * * * * double d = 1.7888889988996678;
> * * * * long double ld = 1.7888889988996678998877L;
>
> * * * * for (int i = 0; i<=DBL_DIG;i++) {
> * * * * * * * * printf("i=%d: %.15g\n",i,roundto(d,i));
> * * * * }
> * * * * printf("\n * * *1.7888889988996678\n");
> * * * * for (int i = 0; i<=LDBL_DIG;i++) {
> * * * * * * * * printf("i=%d: %.18Lg\n",i,roundtol(ld,i));
> * * * * }
> * * * * printf("\n * * *1.7888889988996678998877L\n");
> * * * * return 0;
>
> }
>
> --------------------------------------------------------------------
> I would propose it to add it to the FAQ.

The snippets solution, tweaked a little bit:

#include <math.h>
/* round number n to d decimal points */
long double roundl(const long double n, const unsigned d)
{
long double p = powl(10., d);
return floorl(n * p + .5) / p;
}

/* round number n to d decimal points */
double roundd(const double n, const unsigned d)
{
return (double) roundl((long double) n, d);
}

/* round number n to d decimal points */
double roundf(const float n, const unsigned d)
{
return (float) roundl((long double) n, d);
}
#ifdef UNIT_TEST
#include <stdio.h>
#include <stdlib.h>
#include <float.h>
int main(void)
{
long double pi = 3.1415926535897932384626433832795;
long double npi = -pi;
unsigned digits;
for (digits = 0; digits <= LDBL_DIG; digits++) {
printf("Rounding by printf gives: %20.*f\n",
digits, pi);
printf("Rounding approximation by function gives: %20.*f\n",
LDBL_DIG, roundl(pi, digits));
printf("Rounding approximation by function gives: %20.*f\n",
DBL_DIG, roundd(pi, digits));
printf("Rounding approximation by function gives: %20.*f\n\n",
FLT_DIG, roundf(pi, digits));
}
for (digits = 0; digits <= LDBL_DIG; digits++) {
printf("Rounding by printf gives: %20.*f\n",
digits, npi);
printf("Rounding approximation by function gives: %20.*f\n",
LDBL_DIG, roundl(npi, digits));
printf("Rounding approximation by function gives: %20.*f\n",
DBL_DIG, roundd(npi, digits));
printf("Rounding approximation by function gives: %20.*f\n\n",
FLT_DIG, roundf(npi, digits));
}
return 0;
}
#endif
/*
Rounding by printf gives: 3
Rounding approximation by function gives: 3.000000000000000
Rounding approximation by function gives: 3.000000000000000
Rounding approximation by function gives: 3.000000

Rounding by printf gives: 3.1
Rounding approximation by function gives: 3.100000000000000
Rounding approximation by function gives: 3.100000000000000
Rounding approximation by function gives: 3.100000

Rounding by printf gives: 3.14
Rounding approximation by function gives: 3.140000000000000
Rounding approximation by function gives: 3.140000000000000
Rounding approximation by function gives: 3.140000

Rounding by printf gives: 3.142
Rounding approximation by function gives: 3.142000000000000
Rounding approximation by function gives: 3.142000000000000
Rounding approximation by function gives: 3.142000

Rounding by printf gives: 3.1416
Rounding approximation by function gives: 3.141600000000000
Rounding approximation by function gives: 3.141600000000000
Rounding approximation by function gives: 3.141600

Rounding by printf gives: 3.14159
Rounding approximation by function gives: 3.141590000000000
Rounding approximation by function gives: 3.141590000000000
Rounding approximation by function gives: 3.141590

Rounding by printf gives: 3.141593
Rounding approximation by function gives: 3.141593000000000
Rounding approximation by function gives: 3.141593000000000
Rounding approximation by function gives: 3.141593

Rounding by printf gives: 3.1415927
Rounding approximation by function gives: 3.141592700000000
Rounding approximation by function gives: 3.141592700000000
Rounding approximation by function gives: 3.141593

Rounding by printf gives: 3.14159265
Rounding approximation by function gives: 3.141592650000000
Rounding approximation by function gives: 3.141592650000000
Rounding approximation by function gives: 3.141593

Rounding by printf gives: 3.141592654
Rounding approximation by function gives: 3.141592654000000
Rounding approximation by function gives: 3.141592654000000
Rounding approximation by function gives: 3.141593

Rounding by printf gives: 3.1415926536
Rounding approximation by function gives: 3.141592653600000
Rounding approximation by function gives: 3.141592653600000
Rounding approximation by function gives: 3.141593

Rounding by printf gives: 3.14159265359
Rounding approximation by function gives: 3.141592653590000
Rounding approximation by function gives: 3.141592653590000
Rounding approximation by function gives: 3.141593

Rounding by printf gives: 3.141592653590
Rounding approximation by function gives: 3.141592653590000
Rounding approximation by function gives: 3.141592653590000
Rounding approximation by function gives: 3.141593

Rounding by printf gives: 3.1415926535898
Rounding approximation by function gives: 3.141592653589800
Rounding approximation by function gives: 3.141592653589800
Rounding approximation by function gives: 3.141593

Rounding by printf gives: 3.14159265358979
Rounding approximation by function gives: 3.141592653589790
Rounding approximation by function gives: 3.141592653589790
Rounding approximation by function gives: 3.141593

Rounding by printf gives: 3.141592653589793
Rounding approximation by function gives: 3.141592653589793
Rounding approximation by function gives: 3.141592653589793
Rounding approximation by function gives: 3.141593

Rounding by printf gives: -3
Rounding approximation by function gives: -3.000000000000000
Rounding approximation by function gives: -3.000000000000000
Rounding approximation by function gives: -3.000000

Rounding by printf gives: -3.1
Rounding approximation by function gives: -3.100000000000000
Rounding approximation by function gives: -3.100000000000000
Rounding approximation by function gives: -3.100000

Rounding by printf gives: -3.14
Rounding approximation by function gives: -3.140000000000000
Rounding approximation by function gives: -3.140000000000000
Rounding approximation by function gives: -3.140000

Rounding by printf gives: -3.142
Rounding approximation by function gives: -3.142000000000000
Rounding approximation by function gives: -3.142000000000000
Rounding approximation by function gives: -3.142000

Rounding by printf gives: -3.1416
Rounding approximation by function gives: -3.141600000000000
Rounding approximation by function gives: -3.141600000000000
Rounding approximation by function gives: -3.141600

Rounding by printf gives: -3.14159
Rounding approximation by function gives: -3.141590000000000
Rounding approximation by function gives: -3.141590000000000
Rounding approximation by function gives: -3.141590

Rounding by printf gives: -3.141593
Rounding approximation by function gives: -3.141593000000000
Rounding approximation by function gives: -3.141593000000000
Rounding approximation by function gives: -3.141593

Rounding by printf gives: -3.1415927
Rounding approximation by function gives: -3.141592700000000
Rounding approximation by function gives: -3.141592700000000
Rounding approximation by function gives: -3.141593

Rounding by printf gives: -3.14159265
Rounding approximation by function gives: -3.141592650000000
Rounding approximation by function gives: -3.141592650000000
Rounding approximation by function gives: -3.141593

Rounding by printf gives: -3.141592654
Rounding approximation by function gives: -3.141592654000000
Rounding approximation by function gives: -3.141592654000000
Rounding approximation by function gives: -3.141593

Rounding by printf gives: -3.1415926536
Rounding approximation by function gives: -3.141592653600000
Rounding approximation by function gives: -3.141592653600000
Rounding approximation by function gives: -3.141593

Rounding by printf gives: -3.14159265359
Rounding approximation by function gives: -3.141592653590000
Rounding approximation by function gives: -3.141592653590000
Rounding approximation by function gives: -3.141593

Rounding by printf gives: -3.141592653590
Rounding approximation by function gives: -3.141592653590000
Rounding approximation by function gives: -3.141592653590000
Rounding approximation by function gives: -3.141593

Rounding by printf gives: -3.1415926535898
Rounding approximation by function gives: -3.141592653589800
Rounding approximation by function gives: -3.141592653589800
Rounding approximation by function gives: -3.141593

Rounding by printf gives: -3.14159265358979
Rounding approximation by function gives: -3.141592653589790
Rounding approximation by function gives: -3.141592653589790
Rounding approximation by function gives: -3.141593

Rounding by printf gives: -3.141592653589793
Rounding approximation by function gives: -3.141592653589793
Rounding approximation by function gives: -3.141592653589793
Rounding approximation by function gives: -3.141593
*/

CBFalconer
Guest
Posts: n/a

 02-25-2008
jacob navia wrote:
>
> "How can I round a number to x decimal places" ?
>
> This question keeps appearing. I would propose the following
>

.... snip 75 or so lines ...

Why all this gyration? I found the following in the c standard:

7.12.9.6 The round functions
Synopsis
[#1]
#include <math.h>
double round(double x);
float roundf(float x);
long double roundl(long double x);

Description

[#2] The round functions round their argument to the nearest
integer value in floating-point format, rounding halfway
cases away from zero, regardless of the current rounding
direction.

Returns

[#3] The round functions return the rounded integer value.

--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>

--
Posted via a free Usenet account from http://www.teranews.com

Ben Pfaff
Guest
Posts: n/a

 02-26-2008
CBFalconer <(E-Mail Removed)> writes:

> jacob navia wrote:
>>
>> "How can I round a number to x decimal places" ?
>>
>> This question keeps appearing. I would propose the following
>>

> ... snip 75 or so lines ...
>
> Why all this gyration? I found the following in the c standard:
>
> 7.12.9.6 The round functions

Those functions are new in C99.
--
char a[]="\n .CJacehknorstu";int putchar(int);int main(void){unsigned long b[]
={0x67dffdff,0x9aa9aa6a,0xa77ffda9,0x7da6aa6a,0xa6 7f6aaa,0xaa9aa9f6,0x11f6},*p
=b,i=24;for(;p+=!*p;*p/=4)switch(0[p]&3)case 0:{return 0;for(p--;i--;i--)case+
2:{i++;if(i)break;else default:continue;if(0)case 1utchar(a[i&15]);break;}}}

user923005
Guest
Posts: n/a

 02-26-2008
On Feb 25, 4:29*pm, Ben Pfaff <(E-Mail Removed)> wrote:
> CBFalconer <(E-Mail Removed)> writes:
> > jacob navia wrote:

>
> >> "How can I round a number to x decimal places" ?

>
> >> This question keeps appearing. I would propose the following

>
> > ... snip 75 or so lines ...

>
> > Why all this gyration? *I found the following in the c standard:

>
> > * 7.12.9.6 *The round functions

>
> Those functions are new in C99.

And they don't round to x decimal places, unless x happens to be
zero. (Admittedly, you could manually scale it.)

Keith Thompson
Guest
Posts: n/a

 02-26-2008
Ben Pfaff <(E-Mail Removed)> writes:
> CBFalconer <(E-Mail Removed)> writes:
>> jacob navia wrote:
>>> "How can I round a number to x decimal places" ?
>>>
>>> This question keeps appearing. I would propose the following
>>>

>> ... snip 75 or so lines ...
>>
>> Why all this gyration? I found the following in the c standard:
>>
>> 7.12.9.6 The round functions

>
> Those functions are new in C99.

So are floorl and log10l, which jacob's code uses; it also mixes
declarations and statements within a block. An implementation that
can handle jacob's code should provide the round functions.

--
Keith Thompson (The_Other_Keith) <(E-Mail Removed)>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"

user923005
Guest
Posts: n/a

 02-26-2008
On Feb 25, 10:15*pm, Keith Thompson <(E-Mail Removed)> wrote:
> Ben Pfaff <(E-Mail Removed)> writes:
> > CBFalconer <(E-Mail Removed)> writes:
> >> jacob navia wrote:
> >>> "How can I round a number to x decimal places" ?

>
> >>> This question keeps appearing. I would propose the following

>
> >> ... snip 75 or so lines ...

>
> >> Why all this gyration? *I found the following in the c standard:

>
> >> * 7.12.9.6 *The round functions

>
> > Those functions are new in C99.

>
> So are floorl and log10l, which jacob's code uses; it also mixes
> declarations and statements within a block. *An implementation that
> can handle jacob's code should provide the round functions.

You will still have to multiply and divide by powers of 10 and use
floor() to achieve the same thing because the C99 round() functions
round to nearest integer. They do not round to nearest k decimal
places.

CBFalconer
Guest
Posts: n/a

 02-26-2008
user923005 wrote:
>

.... snip float rounding discussion ...
>
> You will still have to multiply and divide by powers of 10 and use
> floor() to achieve the same thing because the C99 round() functions
> round to nearest integer. They do not round to nearest k decimal
> places.

Are you claiming that such multiplication and division by 10 is too
complex for the average reader of c.l.c?

--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>

--
Posted via a free Usenet account from http://www.teranews.com

user923005
Guest
Posts: n/a

 02-27-2008
On Feb 26, 2:24*pm, CBFalconer <(E-Mail Removed)> wrote:
> user923005 wrote:
>
> ... snip float rounding discussion ...
>
>
>
> > You will still have to multiply and divide by powers of 10 and use
> > floor() to achieve the same thing because the C99 round() functions
> > round to nearest integer. *They do not round to nearest k decimal
> > places.

>
> Are you claiming that such multiplication and division by 10 is too
> complex for the average reader of c.l.c? *

No, but I am claiming that using the C99 functions to round to N
digits will take twice as much work as a function that does it
directly, since the multiplication and division by a power of ten and
the floor function are all that is necessary in either case. And so
while you can round to N digits using the C99 rounding functions, it
really does not make a lot of sense to do it that way.

CBFalconer
Guest
Posts: n/a

 02-27-2008
user923005 wrote:
> CBFalconer <(E-Mail Removed)> wrote:
>> user923005 wrote:
>>
>> ... snip float rounding discussion ...
>>
>>> You will still have to multiply and divide by powers of 10 and
>>> use floor() to achieve the same thing because the C99 round()
>>> functions round to nearest integer. They do not round to
>>> nearest k decimal places.

>>
>> Are you claiming that such multiplication and division by 10 is
>> too complex for the average reader of c.l.c?

>
> No, but I am claiming that using the C99 functions to round to N
> digits will take twice as much work as a function that does it
> directly, since the multiplication and division by a power of
> ten and the floor function are all that is necessary in either
> case. And so while you can round to N digits using the C99
> rounding functions, it really does not make a lot of sense to do
> it that way.

Let me also point out that such rounding is rarely needed. Most of
the time maintaining the original alleged precision and rounding
only the output, via printf, is needed.

--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>

--
Posted via a free Usenet account from http://www.teranews.com