Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Decimal rounding function

1 view
Skip to first unread message

Bubba

unread,
Nov 21, 2009, 5:37:02 PM11/21/09
to
Greetings to all,

I'm searching for cheap, quick and easy rounding function in C, but (there
had to be but!) without any libraries. In other words, is there a sane
mathematical (or any other, for that matter) way that can be implemented
in C and round arbitrary number of decimal places them to desired decimal
places?

So, basically, something like this:

double round (double number, unsigned decimalPlaces) {
/* some magic here */ }

Basic point is to make it portable for everything from Motorola 68000 to
embedded ARM or latest gaming x64 CPU.

I tried doing it myself but couldn't even begin being puzzled about
determining number of decimal places in the first place, let alone doing
any rounding with them.

Also did some Googling research but found only solutions with strings and
similar tricks (which I was acquainted with) or written in C++. Appreciate
any help or hint.

TIA!

--
Vencavam se draga popodne u sredu �|� .-'``'-.,_,.-'``'-.,
za taj slucaj surim svinju od sto kila �|� '-.,_,.-'``'-.,_,.-'
dvojica svedoci mene ce privedu �|� � http://math2.ath.cx
dodji da se vencas i ti s mene mila. �|� '-.,_,.-'``'-.,_,.-'

Seebs

unread,
Nov 21, 2009, 5:44:42 PM11/21/09
to
On 2009-11-21, Bubba <nick...@banelli.biz.invalid> wrote:
> I'm searching for cheap, quick and easy rounding function in C, but (there
> had to be but!) without any libraries. In other words, is there a sane
> mathematical (or any other, for that matter) way that can be implemented
> in C and round arbitrary number of decimal places them to desired decimal
> places?

Steal code from a library which does this. BSD libc has a working one (some
versions may still have bugs) which you can embed in nearly anything.

-s
--
Copyright 2009, all wrongs reversed. Peter Seebach / usenet...@seebs.net
http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!

Ben Bacarisse

unread,
Nov 21, 2009, 6:55:55 PM11/21/09
to
Bubba <nick...@banelli.biz.invalid> writes:

> I'm searching for cheap, quick and easy rounding function in C, but (there
> had to be but!) without any libraries. In other words, is there a sane
> mathematical (or any other, for that matter) way that can be implemented
> in C and round arbitrary number of decimal places them to desired decimal
> places?
>
> So, basically, something like this:
>
> double round (double number, unsigned decimalPlaces) {
> /* some magic here */ }

Just a word of warning: the exact answer is often not representable so
you might be surprised by the result. It all depends on what you are
doing with it.

<snip>
--
Ben.

Gordon Burditt

unread,
Nov 21, 2009, 7:25:16 PM11/21/09
to
>I'm searching for cheap, quick and easy rounding function in C, but (there
>had to be but!) without any libraries.

You can't do much of anything without libraries, even exit().
Standard C says you are allowed to use them, and that trumps homework
assignments.

>In other words, is there a sane
>mathematical (or any other, for that matter) way that can be implemented
>in C and round arbitrary number of decimal places them to desired decimal
>places?

Binary floating point cannot usually represent the result from such
a function, so although the function may be able to create an
accurate answer, putting it in a binary floating point number
introduces rounding error.

>So, basically, something like this:
>
>double round (double number, unsigned decimalPlaces) {

This function name is already taken in C99.


>/* some magic here */ }

One approach to round to N decimal places is to multiply by 10**N,
round() (the Standard C function), then divide by 10**N.

(** is an integer exponentiation operator from, for example, FORTRAN,
and not available in C, but for small integer values of decimalPlaces,
you can use table lookup or loops with integer math, and for larger
values you can use pow() with less accuracy).

If you don't have round() (C90 doesn't have it), you can use floor()
(which is present in C90 and C99):

#define my_round(x) floor((x)+0.5)

If you don't like floor(), you can use ((int) (x)) (where x is a
double), but this does not work for negative numbers (You can fix
this by splitting it into two cases). It also fails if the result
won't fit in an int. This is harder to work around.

You didn't specify anything like round-to-even and there's no
guarantee that these substitutes will work that way.

If you mostly use a small integer constant for the number of decimal
places, you could use something like:

#define roundto3(x) (round(1000.0 * (x))/1000.0)

>Basic point is to make it portable for everything from Motorola 68000 to
>embedded ARM or latest gaming x64 CPU.

You will almost always have rounding error from the mathematically
correct answer with binary floating point, since the exact answer
won't be representable. For example, if you round to 3 decimal
places, the only exact answers will be of the form:

xxxx.000
xxxx.125
xxxx.250
xxxx.375
xxxx.500
xxxx.625
xxxx.750
xxxx.875

>I tried doing it myself but couldn't even begin being puzzled about
>determining number of decimal places in the first place, let alone doing
>any rounding with them.

Don't even try to determine the number of decimal places in a number.
For example, for 0.001 < x < 0.002, the number of decimal places
to the right of the decimal point in x is somewhere between 4 and
infinity, inclusive, and it's highly sensitive to the slightest
rounding error.

>Also did some Googling research but found only solutions with strings and
>similar tricks (which I was acquainted with) or written in C++. Appreciate
>any help or hint.

You can get an exact result with, for example, sprintf(), but if you try
putting the result back into a binary floating-point number with
sscanf(), you introduce rounding error.

Keith Thompson

unread,
Nov 21, 2009, 8:27:49 PM11/21/09
to
Bubba <nick...@banelli.biz.invalid> writes:
> Greetings to all,
>
> I'm searching for cheap, quick and easy rounding function in C, but (there
> had to be but!) without any libraries. In other words, is there a sane
> mathematical (or any other, for that matter) way that can be implemented
> in C and round arbitrary number of decimal places them to desired decimal
> places?
>
> So, basically, something like this:
>
> double round (double number, unsigned decimalPlaces) {
> /* some magic here */ }
>
> Basic point is to make it portable for everything from Motorola 68000 to
> embedded ARM or latest gaming x64 CPU.
>
> I tried doing it myself but couldn't even begin being puzzled about
> determining number of decimal places in the first place, let alone doing
> any rounding with them.
>
> Also did some Googling research but found only solutions with strings and
> similar tricks (which I was acquainted with) or written in C++. Appreciate
> any help or hint.

(The name "round" is already taken.)

There's no such function in the standard, and few such functions
floating (ahem) around out there, because it's really not as useful
as you might think.

Rounding a floating-point to a specified number of decimal places is
useful only if you're producing a string representation of the number.
(Well, there might be *some* use for it, but I can't think of any.)
And if you're doing that, you might as well just produce the string
directly.

round(1.375, 1) should give you 1.4, but 1.4 cannot be represented
exactly in binary floating-point. You might get something like
1.399999999999999911182158029987476766109466552734375, which depending
on how you print it, might come out as "1.3".

What are you really trying to accomplish? What do you intended to
do with the rounded number once you've generated it? Why not just
keep it in full precision until you're ready to truncate it when
printing it or converting it to a string?

--
Keith Thompson (The_Other_Keith) ks...@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"

Boon

unread,
Nov 22, 2009, 6:29:12 AM11/22/09
to
Seebs wrote:

> Steal code from a library which does this. BSD libc has a working one (some
> versions may still have bugs) which you can embed in nearly anything.

Yours is a poor choice of words.

Taking code from BSD-licensed software is not "stealing" in any way.

Boon

unread,
Nov 22, 2009, 6:32:21 AM11/22/09
to
Bubba wrote:

> I'm searching for cheap, quick and easy rounding function in C, but (there
> had to be but!) without any libraries. In other words, is there a sane
> mathematical (or any other, for that matter) way that can be implemented
> in C and round arbitrary number of decimal places them to desired decimal
> places?

What Every Computer Scientist Should Know About Floating-Point Arithmetic
http://docs.sun.com/source/806-3568/ncg_goldberg.html

Malcolm McLean

unread,
Nov 22, 2009, 9:51:08 AM11/22/09
to

"Bubba" <nick...@banelli.biz.invalid> wrote in message
> I'm searching for cheap, quick and easy rounding function in C,.

> In other words, is there a sane
> mathematical (or any other, for that matter) way that can be implemented
> in C and round arbitrary number of decimal places them to desired decimal
> places?
>
As Keith pointed out, important cases like 0.1 have no exact representation
in typical binary-based floating point formats.
So the thing to do is to use double, then do all your calcuations in whole
integers. So if you work to 3 decimal palces, everything is multiplied by
1000. Don't be tempted to use long or int. For this purpose, you'll find
double is the best integer type.
Note that multiplications and divisions need to be scaled.


Malcolm McLean

unread,
Nov 22, 2009, 9:53:57 AM11/22/09
to
"Gordon Burditt" <gordon...@burditt.org> wrote in message

>
> You can't do much of anything without libraries, even exit().
> Standard C says you are allowed to use them, and that trumps homework
> assignments.
>
But the C code might be a preliminary to an assembler program, to give just
one case where standard libraries might not be available. Not all the world
is a hosted implementation.


Willem

unread,
Nov 22, 2009, 9:55:35 AM11/22/09
to
Malcolm McLean wrote:
) As Keith pointed out, important cases like 0.1 have no exact representation
) in typical binary-based floating point formats.
) So the thing to do is to use double, then do all your calcuations in whole
) integers. So if you work to 3 decimal palces, everything is multiplied by
) 1000. Don't be tempted to use long or int. For this purpose, you'll find
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
) double is the best integer type.

Why is that ?

) Note that multiplications and divisions need to be scaled.


SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT

Malcolm McLean

unread,
Nov 22, 2009, 10:51:04 AM11/22/09
to

"Willem" <wil...@stack.nl> wrote in message news:

> Malcolm McLean wrote:
> ) 1000. Don't be tempted to use long or int. For this purpose, you'll find
> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> ) double is the best integer type.
>
> Why is that ?
>
integer types do implicit rounding towards zero, which often needs to be
handled very carefully. (The whole point is to keep the precision). Also
they typically have less range than a double. Then a double degrades
gracefully on overflow, which is most likely what you want. Also you'll use
fewer casts converting between your special representation and the ultimate
normal real representations you'll probably use.

Flash Gordon

unread,
Nov 22, 2009, 10:51:28 AM11/22/09
to
Willem wrote:
> Malcolm McLean wrote:
> ) As Keith pointed out, important cases like 0.1 have no exact representation
> ) in typical binary-based floating point formats.
> ) So the thing to do is to use double, then do all your calcuations in whole
> ) integers. So if you work to 3 decimal palces, everything is multiplied by
> ) 1000. Don't be tempted to use long or int. For this purpose, you'll find
> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> ) double is the best integer type.
>
> Why is that ?

He might be thinking of size. If long is 4 bytes and double is 8 (not
unusual) then you actually have more range of integers (with a step of
1) in a double than a long. Of course, the C99 type long long is likely
to be better if you need the range as it is 8 bytes for the integer
part! I have seen pre-long-long code which uses this technique successfully.
--
Flash Gordon

Seebs

unread,
Nov 22, 2009, 12:08:24 PM11/22/09
to
On 2009-11-22, Boon <root@localhost> wrote:
> Seebs wrote:
>> Steal code from a library which does this. BSD libc has a working one (some
>> versions may still have bugs) which you can embed in nearly anything.

> Yours is a poor choice of words.

No, it's an intentional one.

> Taking code from BSD-licensed software is not "stealing" in any way.

Actualy, it can be, if you don't pay attention to the fine details of the
licensing, but basically agreed.

But "steal" has a long-standing usage in software as a synonym for
"repurpose". As in, yanking a little bit of code from something else and
using it in a new context. I find this usage amusing. I do not consider
it particularly technically precise, but it's idiomatic.

Keith Thompson

unread,
Nov 22, 2009, 1:08:31 PM11/22/09
to

You're making a lot of unsupported assumptions about what the OP wants
to do.

To state the obvious, double is not an integer type. Dividing an odd
number by 2.0 gives you a non-integer. Computing a result beyond
the range of integer values that the type can represent exactly
(typically around 53 bits or so) loses precision. In both cases,
this happens silently. Is this what the OP wants? If so, how did
you reach this conclusion based on the fact that the OP wants a
decimal rounding function?

Malcolm McLean

unread,
Nov 22, 2009, 1:46:06 PM11/22/09
to

"Keith Thompson" <ks...@mib.org> wrote in message

> To state the obvious, double is not an integer type. Dividing an odd
> number by 2.0 gives you a non-integer.
> Is this what the OP wants? If so, how did
> you reach this conclusion based on the fact that the OP wants a
> decimal rounding function?
>
Most people want to accumulate the error. So holding the calculations in
double and then calling floor(x + 0.5) to get the result to 3 decimal places
(in scaled arithmetic) is probably what he wants. Wanting to round towards
zero and throw away the errors, which is what will happen if you use
integers, is an unusual thing to want.


Flash Gordon

unread,
Nov 22, 2009, 2:57:02 PM11/22/09
to
Malcolm McLean wrote:
> "Keith Thompson" <ks...@mib.org> wrote in message
>> To state the obvious, double is not an integer type. Dividing an odd
>> number by 2.0 gives you a non-integer.
>> Is this what the OP wants? If so, how did
>> you reach this conclusion based on the fact that the OP wants a
>> decimal rounding function?
>>
> Most people want to accumulate the error.

That is a very big assumption. In a lot of financial applications you
are specifically required (sometimes by law) to *not* accumulate error.

> So holding the calculations in
> double and then calling floor(x + 0.5) to get the result to 3 decimal places
> (in scaled arithmetic) is probably what he wants. Wanting to round towards
> zero and throw away the errors, which is what will happen if you use
> integers, is an unusual thing to want.

You are making big assumptions on the application domain based on no
knowledge. There are lots of possible reasons to not want to do that.
--
Flash Gordon

Flash Gordon

unread,
Nov 22, 2009, 2:58:23 PM11/22/09
to
Malcolm McLean wrote:
> "Keith Thompson" <ks...@mib.org> wrote in message
>> To state the obvious, double is not an integer type. Dividing an odd
>> number by 2.0 gives you a non-integer.
>> Is this what the OP wants? If so, how did
>> you reach this conclusion based on the fact that the OP wants a
>> decimal rounding function?
>>
> Most people want to accumulate the error.

That is a very big assumption. In a lot of financial applications you
are specifically required (sometimes by law) to *not* accumulate error.

> So holding the calculations in
> double and then calling floor(x + 0.5) to get the result to 3 decimal places
> (in scaled arithmetic) is probably what he wants. Wanting to round towards
> zero and throw away the errors, which is what will happen if you use
> integers, is an unusual thing to want.

You are making big assumptions on the application domain based on no

Flash Gordon

unread,
Nov 22, 2009, 3:00:59 PM11/22/09
to
Malcolm McLean wrote:
> "Keith Thompson" <ks...@mib.org> wrote in message
>> To state the obvious, double is not an integer type. Dividing an odd
>> number by 2.0 gives you a non-integer.
>> Is this what the OP wants? If so, how did
>> you reach this conclusion based on the fact that the OP wants a
>> decimal rounding function?
>>
> Most people want to accumulate the error.

That is a very big assumption. In a lot of financial applications you
are specifically required (sometimes by law) to *not* accumulate error.

> So holding the calculations in
> double and then calling floor(x + 0.5) to get the result to 3 decimal places
> (in scaled arithmetic) is probably what he wants. Wanting to round towards
> zero and throw away the errors, which is what will happen if you use
> integers, is an unusual thing to want.

You are making big assumptions on the application domain based on no

Nobody

unread,
Nov 22, 2009, 3:05:58 PM11/22/09
to
On Sun, 22 Nov 2009 10:08:31 -0800, Keith Thompson wrote:

> To state the obvious, double is not an integer type.

It is capable of exactly representing many integers, often with more bits
than any C90 integer type.

> Dividing an odd
> number by 2.0 gives you a non-integer.

Using integers, dividing an odd number by two gives you an incorrect
result.

> Computing a result beyond
> the range of integer values that the type can represent exactly
> (typically around 53 bits or so) loses precision.

The equivalent situation with an integer type results in a much larger
error (overflow).

> In both cases, this happens silently.

Integer overflow and truncation are both silent, and not easy to test for.
With doubles, both of these can be easily tested for afterwards. Also, in
C99 you may be able to trap an inexact result.


Malcolm McLean

unread,
Nov 22, 2009, 3:07:50 PM11/22/09
to
"Flash Gordon" <sm...@spam.causeway.com> wrote in message news:

> Malcolm McLean wrote:
>>>
>> Most people want to accumulate the error.
>
> That is a very big assumption. In a lot of financial applications you are
> specifically required (sometimes by law) to *not* accumulate error.
>
In which case you'll want to call floor(x + 0.5) explictly to make it
obvious that ypu are throwing away the errors at the points designated by
law. Just leaving it to implied rounding in integer arithmetic is inviting a
visit from the serious fraud office.


Keith Thompson

unread,
Nov 22, 2009, 3:19:04 PM11/22/09
to
Nobody <nob...@nowhere.com> writes:
> On Sun, 22 Nov 2009 10:08:31 -0800, Keith Thompson wrote:
>
>> To state the obvious, double is not an integer type.
>
> It is capable of exactly representing many integers, often with more bits
> than any C90 integer type.

Yes. It's still not an integer type.

>> Dividing an odd
>> number by 2.0 gives you a non-integer.
>
> Using integers, dividing an odd number by two gives you an incorrect
> result.

That depends on what result you wanted. For example, if I want the
index of an element at the middle of an array, if (min+max)/2 gives me
7.5 that's not very useful; I really want 7.

>> Computing a result beyond
>> the range of integer values that the type can represent exactly
>> (typically around 53 bits or so) loses precision.
>
> The equivalent situation with an integer type results in a much larger
> error (overflow).
>
>> In both cases, this happens silently.
>
> Integer overflow and truncation are both silent, and not easy to test for.
> With doubles, both of these can be easily tested for afterwards. Also, in
> C99 you may be able to trap an inexact result.

Both double and long int, for example, can be used to represent
integers. Both are imperfect representations of the infinite set of
mathematical integers; whichever one you choose, you'll have to work
around some problems. There are some cases where a floating-point
type is the best choice, but I don't think they're particularly
common. (Malcolm McLean was arguing that double is the right choice,
with very little basis for that assumption.)

Flash Gordon

unread,
Nov 22, 2009, 4:23:38 PM11/22/09
to

No, it isn't inviting a visit by the SFO. I like a few others here
actually get paid to work on software that does financial calculations,
in my case including calculating certain types of tax.

We do a lot of calculations using a scaled long, and we always know what
we are doing in terms of rounding. Some of the software predates long
long being a common extension, so it tends to use double when we need an
integer type larger than 32 bits, but that means we have to be a *lot*
more careful than we would using an integer type. An integer type would
(in our case) give an obviously wrong result when it does not work,
double gives a subtly wrong result, which is MUCH more likely to get us
in trouble.
--
Flash Gordon

io_x

unread,
Nov 23, 2009, 4:49:46 AM11/23/09
to
"Keith Thompson" ha scritto nel messaggio news:lnocmvq...@nuthaus.mib.org...

> What are you really trying to accomplish? What do you intended to
> do with the rounded number once you've generated it?

i will save it but not in the string reppresentation (because that number
has to be used)

> Why not just
> keep it in full precision until you're ready to truncate it when
> printing it or converting it to a string?

because the result of computation has to be round


Nick Keighley

unread,
Nov 24, 2009, 9:16:46 AM11/24/09
to
On 23 Nov, 09:49, "io_x" <a...@b.c.invalid> wrote:
> "Keith Thompson" ha scritto nel messaggionews:lnocmvq...@nuthaus.mib.org...


> > What are you really trying to accomplish?  What do you intended to
> > do with the rounded number once you've generated it?
>
> i will save it

why?

> but not in the string reppresentation (because that number
> has to be used)

what for?

> > Why not just
> > keep it in full precision until you're ready to truncate it when
> > printing it or converting it to a string?
>
> because the result of computation has to be round

why? and what does "round" mean?

The usual reason for "rounding" something is that you're going to show
it to a person.

io_x

unread,
Nov 26, 2009, 2:02:21 AM11/26/09
to

"Nick Keighley" <nick_keigh...@hotmail.com> ha scritto nel messaggio
news:37b5d0c6-3806-4562...@z7g2000vbl.googlegroups.com...

why?

what for?

#it is only my hobby program for doing operations like what does
#our bank to our account
#
#i can consider one bank account; each operation on that account has to
#be saved in the round form (because each operation *has* to do its rounding).
#it has to be saved because that number should be used

#for what "round" mean...
#for example i consider the C language round mode function for unsigned:
#[that round is round(number, 0)]
#round(x.x0x1x2x3x4x5x6...xn, 2) mean:
#find the machine reppresentation y more near to the number
# x.x0x10000000000000...
#or better find the machine representation y of the number
# x.x0x10000000000000..
#with "|y-x.x0x100000000...|<e=0.0000...0001"
#where "e" dipend from the fixed point number representation

Nick Keighley

unread,
Nov 26, 2009, 3:41:17 AM11/26/09
to
your quoting style is very odd


On 26 Nov, 07:02, "io_x" <a...@b.c.invalid> wrote:
> "Nick Keighley" <nick_keighley_nos...@hotmail.com> ha scritto nel messaggionews:37b5d0c6-3806-4562...@z7g2000vbl.googlegroups.com...


> On 23 Nov, 09:49, "io_x" <a...@b.c.invalid> wrote:
> > "Keith Thompson" ha scritto nel
> > messaggionews:lnocmvq...@nuthaus.mib.org...


> > > What are you really trying to accomplish? What do you intended to
> > > do with the rounded number once you've generated it?
>
> > i will save it
>
> why?
>
> > but not in the string reppresentation (because that number
> > has to be used)
>
> what for?
>
> > > Why not just
> > > keep it in full precision until you're ready to truncate it when
> > > printing it or converting it to a string?
>
> > because the result of computation has to be round
>
> why? and what does "round" mean?
>
> The usual reason for "rounding" something is that you're going to show
> it to a person.

...or a financial calculation


> #it is only my hobby program for doing operations like what does
> #our bank to our account

ah. Money. I'd expect a bank accoun to round to the penny (cent). This
is a t least good enough for a toy program. Why not just store the
number of pennies (cents)? No floating point needed.

> #i can consider one bank account; each operation on that account has to
> #be saved in the round form (because each operation *has* to do its rounding).
> #it has to be saved because that number should be used
>
> #for what "round" mean...
> #for example i consider the C language round mode function for unsigned:
> #[that round is round(number, 0)]
> #round(x.x0x1x2x3x4x5x6...xn,  2) mean:
> #find the machine reppresentation y more near to the number
> # x.x0x10000000000000...
> #or better find the machine representation y of the number
> # x.x0x10000000000000..
> #with "|y-x.x0x100000000...|<e=0.0000...0001"
> #where "e" dipend from the fixed point number representation

all sounds a bit complicated for a simple bank account emulator

Gordon Burditt

unread,
Nov 26, 2009, 4:07:24 AM11/26/09
to
>The usual reason for "rounding" something is that you're going to show
>it to a person.

I disagree. There are lots of reasons for rounding, especially in
commerce, that don't have to involve "showing it to a person". The
"showing it to a person" rounding can usually be accomplished with
formats in the *printf family of functions. Explicit rounding is
mostly used for other reasons.

- Telephone calls are often rounded up to the next higher whole minute
for billing purposes. Telephone companies will insist that this is
an essential part of the calculation.

- Sales tax is rounded in a perhaps convoluted way to a whole cent.

- Bank interest is rounded to whole cents. For that matter, the
amount of just about *any* bank account transaction (and balance)
has to be an exact multiple of the minimum unit of the currency
involved (1 cent for the US dollar).

- There are a number of explicit rounding steps required in the
process of computing US income tax, although most of them aren't
needed by typical filers of the short form. (There are also a
surprising number of times where the forms *should* say "if less
than zero, enter zero", but don't.)

- When you create a graph, it is common practice to have the
tic marks on both axes represent nice, round numbers, even if the
data aren't. For example if Y ranges from 2.7 to 6.6, the top
and bottom of the graph might be at 8.0 and 2.0, with labels at
4.0 and 6.0. (Note: although C doesn't have support for graphics
hardware, you can do "ascii art" graphs with minimal assumptions,
and creating a 2-D array of pixels, filling them in, and then
compressing it into an application-dependent file format like
.jpeg can be done in standard C. Some other program can display it.)

- In engineering, one often has to round up or down to conform to
standard available parts. For example, it's difficult to find
4.173 ampere fuses (you would probably have to have them custom-made),
but 5-ampere fuses are common. Parts also have tolerances, like
10%, 5%, or 1% resistors. Lumber is available in certain sizes,
and to make things more confusing, a 2x4 isn't 2 inches by 4
inches. I think this involves much more than making nice numbers
to show to a person for the parts list. And how many people do
you know who wear (USA) size 7.13873057972392 shoes and a (USA)
size 34.7823 B.572 bra?

- Calculation of complicated floating-point functions (e.g. trig
functions, logarithms, etc.) to give answers accurate to 1 unit
in the last place may require calculating with a few bits extra
precision, and then rounding. For the stuff in the math library,
this should be already done by the C library or the hardware (for
a quality implementation - which isn't guaranteed by C). For
stuff not in the math library, you may have to do it yourself if
you require the best accuracy possible.

bartc

unread,
Nov 26, 2009, 4:37:20 AM11/26/09
to
Nick Keighley wrote:

> On 26 Nov, 07:02, "io_x" <a...@b.c.invalid> wrote:

>> The usual reason for "rounding" something is that you're going to
>> show
>> it to a person.
>
> ...or a financial calculation
>
>
>> #it is only my hobby program for doing operations like what does
>> #our bank to our account
>
> ah. Money. I'd expect a bank accoun to round to the penny (cent). This
> is a t least good enough for a toy program. Why not just store the
> number of pennies (cents)? No floating point needed.

Try working out percentages (eg. VAT, interest) using just whole pennies.

--
Bartc

Nick Keighley

unread,
Nov 26, 2009, 4:39:31 AM11/26/09
to
On 26 Nov, 09:07, gordonb.ss...@burditt.org (Gordon Burditt) wrote:

> >The usual reason for "rounding" something is that you're going to show
> >it to a person.
>
> I disagree.  There are lots of reasons for rounding, especially in
> commerce, that don't have to involve "showing it to a person".  The
> "showing it to a person" rounding can usually be accomplished with
> formats in the *printf family of functions.  Explicit rounding is
> mostly used for other reasons.

<snip many reasons for rounding>

consider me suitably refuted

bartc

unread,
Nov 26, 2009, 8:11:07 AM11/26/09
to

"Keith Thompson" <ks...@mib.org> wrote in message
news:lnocmvq...@nuthaus.mib.org...
> Bubba <nick...@banelli.biz.invalid> writes:

> Rounding a floating-point to a specified number of decimal places is
> useful only if you're producing a string representation of the number.
> (Well, there might be *some* use for it, but I can't think of any.)
> And if you're doing that, you might as well just produce the string
> directly.

The long thread 'Rounding double' from Nov 22 2007 gave quite a few reasons
why rounding to decimal places might be useful.

> round(1.375, 1) should give you 1.4, but 1.4 cannot be represented
> exactly in binary floating-point. You might get something like
> 1.399999999999999911182158029987476766109466552734375, which depending
> on how you print it, might come out as "1.3".

If you sent binary 1.39999... to a machine which used it to place a mark on
a rod calibrated in inches and tenths of an inch, the mark will be placed at
the 1.4" mark, as near as can be measured. And maybe these marks are only
needed at 0.1" spacing so you don't want it at 1.375".

> What are you really trying to accomplish? What do you intended to
> do with the rounded number once you've generated it? Why not just
> keep it in full precision until you're ready to truncate it when
> printing it or converting it to a string?

The human world /does/ use decimal arithmetic so rounding to decimals does
make sense, and it needn't be confined to string representations (although
that seemed to be the overwhelming view in that other long thread too).

Anyway if you are transmitting, in binary, a number known only to be
accurate to 2 decimals, how do you ensure that the final string
representation (if any) will only use 2 decimals? You might otherwise get
nonsense displayed.

(For that matter, if a certain number can clearly only be a whole number,
yet is transmitted in floating point (eg. to a function), it makes sense to
round to a whole number first; ie. do round(x,0). Otherwise any noise in the
number can cause problems. And round(x,0) is little different to
round(x,1)).

--
Bartc

Nick Keighley

unread,
Nov 26, 2009, 9:12:33 AM11/26/09
to

your bank charges VAT on your account?

Dik T. Winter

unread,
Nov 26, 2009, 8:18:58 AM11/26/09
to
In article <k%rPm.8823$Ym4....@text.news.virginmedia.com> "bartc" <ba...@freeuk.com> writes:
> Nick Keighley wrote:
...

> > ah. Money. I'd expect a bank accoun to round to the penny (cent). This
> > is a t least good enough for a toy program. Why not just store the
> > number of pennies (cents)? No floating point needed.
>
> Try working out percentages (eg. VAT, interest) using just whole pennies.

If the percentage is a whole number of percents:
amount * percentage / 100.
adjust if that is not the case.
--
dik t. winter, cwi, science park 123, 1098 xg amsterdam, nederland, +31205924131
home: bovenover 215, 1025 jn amsterdam, nederland; http://www.cwi.nl/~dik/

bartc

unread,
Nov 26, 2009, 2:20:26 PM11/26/09
to

"Nick Keighley" <nick_keigh...@hotmail.com> wrote in message
news:4fb2350e-2030-462b...@c3g2000yqd.googlegroups.com...

Don't give them ideas..

--
Bartc

Gordon Burditt

unread,
Nov 26, 2009, 9:18:38 PM11/26/09
to
>Anyway if you are transmitting, in binary, a number known only to be
>accurate to 2 decimals, how do you ensure that the final string
>representation (if any) will only use 2 decimals? You might otherwise get
>nonsense displayed.

If all you are transmitting is the binary representation of a
floating point number, there is no way to ensure that the final
string representation (if any) will only use 2 decimals. There are
only 4 patterns that have exact representations in binary floating
point that will naturally use only two or fewer decimal places:

xxxxx.00
xxxxx.25
xxxxx.50
xxxxx.75
and in any case, there's no way to tell that:
2.50000000000000000000000000000000000000000 as a binary floating point
number has one or 20 significant digits to the right of the decimal point,
as 2.5 and 2.500000000000 are represented the same. You need to transmit
the number of significant digits, or something equivalent, along with the
value.


>(For that matter, if a certain number can clearly only be a whole number,
>yet is transmitted in floating point (eg. to a function), it makes sense to
>round to a whole number first; ie. do
>round(x,0). Otherwise any noise in the

round() is a C99 function that takes *ONE ARGUMENT*. The name is
taken. Find another name for decimal rounding to N digits.

>number can cause problems. And round(x,0) is little different to
>round(x,1)).

decimalround(x,0) can return an exact representation of the rounded
value within a reasonable range. decimalround(x,1) cannot.

bartc

unread,
Nov 27, 2009, 5:25:54 AM11/27/09
to

"Gordon Burditt" <gordon...@burditt.org> wrote in message
news:DfydncGLvNJjq5LW...@posted.internetamerica...

> >Anyway if you are transmitting, in binary, a number known only to be
>>accurate to 2 decimals, how do you ensure that the final string
>>representation (if any) will only use 2 decimals? You might otherwise get
>>nonsense displayed.
>
> If all you are transmitting is the binary representation of a
> floating point number, there is no way to ensure that the final
> string representation (if any) will only use 2 decimals. There are
> only 4 patterns that have exact representations in binary floating
> point that will naturally use only two or fewer decimal places:
>
> xxxxx.00
> xxxxx.25
> xxxxx.50
> xxxxx.75
> and in any case, there's no way to tell that:
> 2.50000000000000000000000000000000000000000 as a binary floating point
> number has one or 20 significant digits to the right of the decimal point,
> as 2.5 and 2.500000000000 are represented the same. You need to transmit
> the number of significant digits, or something equivalent, along with the
> value.

If I want to transmit a number 2.5223987237476 that I know can only really
be the nearest of 2.40, 2.50 and 2.60, I would rather transmit it as
2.500000000000000072 or 2.499999999999999991 (by rounding to 1 decimal) than
as 2.5223987237476.

The tiny deviations from exactly 2.5 are inevitable. Any calculations using
the rounded number will be as accurate as they can be. And printed out in
any number of reasonable places will display as 2.5000000...

>>number can cause problems. And round(x,0) is little different to
>>round(x,1)).
>
> decimalround(x,0) can return an exact representation of the rounded
> value within a reasonable range. decimalround(x,1) cannot.

There seems to be this preoccupation with this exact representation thing.

If you build a stack of 926 1cm cubes, the height should be 9.26m. That 9.26
of course cannot be represented exactly in binary, but is the best
representation possible.

In the same way, decimalround(9.2614779606,2) might not be exactly 9.26, but
is the best possible.

--
Bartc

Gordon Burditt

unread,
Nov 27, 2009, 3:51:55 PM11/27/09
to
>> If all you are transmitting is the binary representation of a
>> floating point number, there is no way to ensure that the final
>> string representation (if any) will only use 2 decimals. There are
>> only 4 patterns that have exact representations in binary floating
>> point that will naturally use only two or fewer decimal places:
>>
>> xxxxx.00
>> xxxxx.25
>> xxxxx.50
>> xxxxx.75
>> and in any case, there's no way to tell that:
>> 2.50000000000000000000000000000000000000000 as a binary floating point
>> number has one or 20 significant digits to the right of the decimal point,
>> as 2.5 and 2.500000000000 are represented the same. You need to transmit
>> the number of significant digits, or something equivalent, along with the
>> value.
>
>If I want to transmit a number 2.5223987237476 that I know can only really
>be the nearest of 2.40, 2.50 and 2.60,

YOU know it, but does the person you're sending to know it? You
need to either send the number of decimal places the number is
supposed to have, along with the number, or you need to have agreed
on this beforehand. (One way to do this is send it as a string.)

>I would rather transmit it as
>2.500000000000000072 or 2.499999999999999991 (by rounding to 1 decimal) than
>as 2.5223987237476.

You cannot tell the number of digits from looking at the (rounded)
number. If you send 2.499999999999991 you can't tell whether that
was supposed to be 1, 2, 3, or 13 digits.

>The tiny deviations from exactly 2.5 are inevitable. Any calculations using
>the rounded number will be as accurate as they can be. And printed out in
>any number of reasonable places will display as 2.5000000...
>
>>>number can cause problems. And round(x,0) is little different to
>>>round(x,1)).
>>
>> decimalround(x,0) can return an exact representation of the rounded
>> value within a reasonable range. decimalround(x,1) cannot.
>
>There seems to be this preoccupation with this exact representation thing.

Usually discussions of rounding also involve getting the exactly-half-way
or almost-exactly-half-way roundings wrong in an unexpected way.

Dann Corbit

unread,
Dec 4, 2009, 3:46:12 PM12/4/09
to
In article <Xns9CCAF03CD7A5...@130.133.1.4>,
nick...@banelli.biz.invalid says...
>
> Greetings to all,
>
> I'm searching for cheap, quick and easy rounding function in C, but (there
> had to be but!) without any libraries. In other words, is there a sane
> mathematical (or any other, for that matter) way that can be implemented
> in C and round arbitrary number of decimal places them to desired decimal
> places?
>
> So, basically, something like this:
>
> double round (double number, unsigned decimalPlaces) {
> /* some magic here */ }
>
> Basic point is to make it portable for everything from Motorola 68000 to
> embedded ARM or latest gaming x64 CPU.
>
> I tried doing it myself but couldn't even begin being puzzled about
> determining number of decimal places in the first place, let alone doing
> any rounding with them.
>
> Also did some Googling research but found only solutions with strings and
> similar tricks (which I was acquainted with) or written in C++. Appreciate
> any help or hint.
>
> TIA!

Probably, you really want something like this:
http://www.alphaworks.ibm.com/tech/decnumber

There is a snippet that does the same thing, but I guess it really won't
accomplish what you want to do in the long run.

If you want accurate decimal math, then use a decimal library.

0 new messages