473,776 Members | 1,650 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

rounding function?

Is there a std lib rounding function that will round a real to a
given number of decimal places? Something like:

double round_it(double number, int decimal_digits)

pass 34.5678, 3 to it and it returns 34.568

Nov 14 '05 #1
6 9021
>Is there a std lib rounding function that will round a real to a
given number of decimal places? Something like:
No. Not in ANSI C.
double round_it(double number, int decimal_digits)

pass 34.5678, 3 to it and it returns 34.568


There is no exact representation of 34.568, or almost every other decimal
number, in binary floating point. Most implementations of floating
point use binary floating point, including the Intel x86 processors.

However, if you can tolerate the inaccuracy, try these:

#include <math.h>
#include <assert.h>
double round_to_intege r(double value)
{
/* No, the case where value is negative is *NOT* a special case */
return floor(value+0.5 );
}
double round_to_n_deci mal_places(doub le value, int n)
{
int i;
double power_of_10;

assert(n >= 0);
/* calculate 10 ** N (FORTRAN expression) */
/* handling the case of n < 0 is left as an exercise */
for (n = 0, power_of_10 = 1.0; n > 0; n++) {
power_of_10 *= 10.0;
}
return round_to_intege r(value * power_of_10)/power_of_10;
}

Note that I absolutely DON'T CARE what's done with the exactly-halfway-in-between
cases of, say, rounding 1.05 to 1 decimal place. The non-exact representation of
decimal fractions pretty much ensures that the exactly-halfway-in-between situation
will hardly ever occur. If you do care, you'll need to handle it specially.
There is also not much consensus about how the exactly-halfway-in-between case
SHOULD be handled, with the major camps being round up, round away from zero,
and round to even.

Gordon L. Burditt
Nov 14 '05 #2

"Curley Q." <cu*****@bogus. net> wrote
Is there a std lib rounding function that will round a real to a
given number of decimal places? Something like:

double round_it(double number, int decimal_digits)

pass 34.5678, 3 to it and it returns 34.568

I tried to write one a couple of years back, and posted it here. The general
consensus was that a good function (that rounds to the nearest decimal
representable by the precision of a double) was impossible to write in ANSI
C with any efficency.

The best way is to cheat

double round_it(double number, int decimal_digs)
{
char buff[128];

sprintf(buff, "%.*g", decimal_digs, number);
return strtod(buff);
}
Nov 14 '05 #3
Maybe this?
#include <math.h>
#include <stdio.h>

double roundit(double d,int dig)
{
long double m = powl(10,dig);
return roundl(d*m) / m;
}

int main(void)
{
double d = 1.1234567891234 56;

for (int i =1;i<15;i++) {
printf("[%3d] %20.15f\n",i,ro undit(d,i));
}

}
This will output:
[ 1] 1.1000000000000 00
[ 2] 1.1200000000000 00
[ 3] 1.1230000000000 00
[ 4] 1.1235000000000 00
[ 5] 1.1234600000000 00
[ 6] 1.1234570000000 00
[ 7] 1.1234568000000 00
[ 8] 1.1234567900000 00
[ 9] 1.1234567890000 00
[ 10] 1.1234567891000 00
[ 11] 1.1234567891200 00
[ 12] 1.1234567891230 00
[ 13] 1.1234567891235 00
[ 14] 1.1234567891234 60
Nov 14 '05 #4
Curley Q. wrote:
Is there a std lib rounding function that will round a real to a given
number of decimal places? Something like:

double round_it(double number, int decimal_digits)

pass 34.5678, 3 to it and it returns 34.568


Here is my solution manipulating the double as a string:

/* round n to ndigits decimal digits */
char* round_it(char *n, int ndigits)
{
int int_digits, point;

for(int_digits = 0; point != '.'; ++int_digits)
point = n[int_digits];
if(n[int_digits + ndigits] >= '5')
++n[int_digits + (ndigits - 1)];

n[int_digits + ndigits] = '\0';

return n;
}

Nov 14 '05 #5

"Curley Q." <cu*****@bogus. net> a écrit dans le message de
news:40******** ******@bogus.ne t...
Curley Q. wrote:
Is there a std lib rounding function that will round a real to a given
number of decimal places? Something like:

double round_it(double number, int decimal_digits)

pass 34.5678, 3 to it and it returns 34.568


Here is my solution manipulating the double as a string:

/* round n to ndigits decimal digits */
char* round_it(char *n, int ndigits)
{
int int_digits, point;

for(int_digits = 0; point != '.'; ++int_digits)
point = n[int_digits];
if(n[int_digits + ndigits] >= '5')
++n[int_digits + (ndigits - 1)];

n[int_digits + ndigits] = '\0';

return n;
}


There are some problems with your solution.

Suppose you receive:
round("12.1",5) ;

You will index beyond the string you are getting
and touching memory you do not own. You assume that
there is a digit at the position of the point + "ndigits".

Another serious problem is that you just increase the
digit before the end alphabetically! !

If you had '9' you will get ':' as the result of your addition.
You do not carry over the digits. '9' should be transformed
into '0' and the same operation should be repeated until
there are no more digits in the whole string. This is called
"carry propagation".

In a more cosmetic way, you could use strchr to eliminate the
loop since you are just looking for a point. You do
char *p = strchr(n,'.');
if (p == NULL)
return n;
int_digits = p - n;

The termination clause of your "for" loop is just that the pointer
points to something different than the '.' char. If you receive
a string without a point you start an infinite loop since the terminating
zero will be ignored (it *is* different than '.') and you will go on
scanning beyond the end of the string with bad consequences:
either a crash or ending in a random fashion when you hit
some byte that has the value of '.'

Using strchr avoids that problem and is maybe faster. strchr
doesn't read beyond the end of the string, respecting the
terminating zero.

But for strings that contain a point, and have more
digits than the specified precision your function will
work. Of course if we do not hit the 9 in the previous
position. :-)

Nov 14 '05 #6
jacob navia wrote:
Jacob, thanks for your comments.
There are some problems with your solution.

Suppose you receive:
round("12.1",5) ;
The code I posted assumes validity of input.
You will index beyond the string you are getting
and touching memory you do not own. You assume that
there is a digit at the position of the point + "ndigits".
A full-fledged version would return the unmodified 1st argument
if the 2nd argument was >= the number of places available.

Another serious problem is that you just increase the
digit before the end alphabetically! !

If you had '9' you will get ':' as the result of your addition.
You do not carry over the digits. '9' should be transformed
into '0' and the same operation should be repeated until
there are no more digits in the whole string. This is called
"carry propagation".
Doh! Good call on this. That's what I get for posting code I
wrote in five minutes and tested twice. Back to the drawing board.
But for strings that contain a point, and have more
digits than the specified precision your function will
work. Of course if we do not hit the 9 in the previous
position. :-)


Nov 14 '05 #7

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

6
3422
by: DaveK | last post by:
I am upgrading an MS Access 97 application which uses the format function to round decimal numbers to two places e.g. format(dblValue, "standard") Having done an initial study of this function I can see no obvious pattern in how it does rounding, it is certainly not bankers rounding. I need to replicate the rounding algorithm used in the new application so that the data will be consistent, so if anyone knows the rounding
8
2087
by: Zorpiedoman | last post by:
Howcome: Dim D as decimal = .5D msgbox d.Round(D, 0) this returns "0" Now when I went to school .5 rounds UP to 1 not DOWN to zero?????!!! Documentation says this, but what the heck are they thinking??? I just don't
2
2642
by: Jiri Nemec | last post by:
Hello all, I have got one table with rounding values, table contains prices and round types. id price_from price_to rounding 1 0 1500 0.1 2 1500 5000 1 3 5000 15000 10 4 15000 0 100
11
6657
by: cj | last post by:
Lets assume all calculations are done with decimal data types so things are as precise as possible. When it comes to the final rounding to cut a check to pay dividends for example in VB rounding seems to be done like this 3.435 = 3.44 3.445 = 3.44 Dim decNbr1 As Decimal
6
4708
by: abcd | last post by:
I am trying to write a rounding function. Rounding to 0.05. e.g. I should get below results 6.125 --6.15 1.699 --1.7 1.1985 --1.20 0.5625 --0.60 Can someone have any sample for this....Plain C/C++ function will also do. I want to write more of a generic function so that it could be used from C/C++ programs so I will avoid using the C# advanced functions.
18
2232
by: jdrott1 | last post by:
i'm trying to round my currency string to end in 9. it's for a pricing application. this is the function i'm using to get the item in currency: FormatCurrency(BoxCost, , , , TriState.True) if an item is 41.87 i want the application to bring it up to 41.89 if an item is 41.84 i want the application to round down to 41.79 does anyone know how i could do this?
5
8013
by: Spoon | last post by:
Hello everyone, I don't understand how the lrint() function works. long lrint(double x); The function returns the nearest long integer to x, consistent with the current rounding mode. It raises an invalid floating-point exception if the magnitude of the rounded value is too large to represent. And it raises an inexact floating-point exception if the return value does not
206
13311
by: md | last post by:
Hi Does any body know, how to round a double value with a specific number of digits after the decimal points? A function like this: RoundMyDouble (double &value, short numberOfPrecisions) It then updates the value with numberOfPrecisions after the decimal
20
5014
by: jacob navia | last post by:
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>
0
9628
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
9464
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
10289
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
10120
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
0
9923
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
6722
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
5493
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
4031
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
3622
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.