468,490 Members | 2,584 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 468,490 developers. It's quick & easy.

Rounding double

md
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
point.

Any help is appreciated.

Thanks.
md
Nov 22 '07
206 11528
jacob navia wrote:
....
This is perfectly OK since double has only 16 decimal digits,
and the first ones in your result appear at 1e-21 (if I counted
Citation please? Where does the C standard impose such requirements for
all implementations?
Nov 22 '07 #51
Mark McIntyre wrote:
jacob navia wrote:
>>Could someone else please share with us the result they get when they
drive this function with inputs of 0.33 and 1 ? I'm getting some
very, very strange results here.
>d:\lcc\mc68\test>type tdouble3.c

I copy-pasted this exact code, and compiled under gcc 4.1.2:

thelinux clc_tests $ ./a.out 0.33
1374389535.0000000000000000000: 0 decimals 1374389535.0000000000000000
1374389535.0000000000000000000: 1 decimals 1374389535.0000000000000000

I'm giving this one a 'strange' score of 'high'
Yes, because stdlib.h is missing. You need it for the prototype of atof.
You saw the warning and then you spread nonsense, like all
your posts.
--
jacob navia
jacob at jacob point remcomp point fr
logiciels/informatique
http://www.cs.virginia.edu/~lcc-win32
Nov 22 '07 #52
James Kuyper wrote:
jacob navia wrote:
...
>This is perfectly OK since double has only 16 decimal digits,
and the first ones in your result appear at 1e-21 (if I counted

Citation please? Where does the C standard impose such requirements for
all implementations?
I changed my function to use DBL_DIG already. See elsethread

--
jacob navia
jacob at jacob point remcomp point fr
logiciels/informatique
http://www.cs.virginia.edu/~lcc-win32
Nov 22 '07 #53
jacob navia wrote:
....
That "footnote" is Annex F, and it IS normative. I cite (again)

F.2 Types
1 The C floating types match the IEC 60559 formats as follows:
The float type matches the IEC 60559 single format.
The double type matches the IEC 60559 double format
Which only applies if __STDC_IEC559__ is #defined by the implementation.
This has been pointed out to you several times. At the very least it
would be nice if you acknowledged this limitation on the validity of
your solution.
Nov 23 '07 #54
jacob navia wrote:
Mark McIntyre wrote:
....
>I copy-pasted this exact code, and compiled under gcc 4.1.2:

thelinux clc_tests $ ./a.out 0.33
1374389535.0000000000000000000: 0 decimals 1374389535.0000000000000000
1374389535.0000000000000000000: 1 decimals 1374389535.0000000000000000

I'm giving this one a 'strange' score of 'high'

Yes, because stdlib.h is missing. You need it for the prototype of atof.
You saw the warning and then you spread nonsense, like all
your posts.
Why was it missing?
Nov 23 '07 #55
jacob navia wrote:
Marco Manfredini wrote:
>Richard Heathfield wrote:
>>jacob navia said:

Richard Heathfield wrote:
Could someone else please share with us the result they get when they
drive this function with inputs of 0.33 and 1 ? I'm getting some very,
very strange results here.
>
d:\lcc\mc68\test>type tdouble3.c

No, I said "someone else". I wouldn't trust you to make a cup of
coffee, let alone a computer program.
long double roundto(long double value, unsigned digits)
{

This is not my function excuse me.

My function returned a double, NOT a long double.

AND THAT IS IMPORTANT!
Yes, for your demonstration, because double gracefully removes the cruft
from the end of your "rounded" value and printf does the rest.
Nov 23 '07 #56
James Kuyper wrote:
jacob navia wrote:
>James Kuyper wrote:
>>jacob navia wrote:
James Kuyper wrote:
jacob navia wrote:
>James Kuyper wrote:
...
>Probably. Your solution is always the best since you did not
>propose any
>
?
I suggesting using sprintf() and sscanf(). I left the details to be
worked out by the reader. Was that too obscure a hint for you?

But he was asking for a function that returns a double, not
asking about PRINTING a double.

OK - so my hint WAS too obscure. Think about it a little while before
you respond again. I'm sure you can figure it out with a little extra
thought. In particular, think about the implications of the fact
that I specified sprintf() rather than printf(), and sscanf() instead
of scanf().

Have you given any more thought to my hint? If not, why did you quote it?

Note: Richard Heathfield has been saying this is impossible, I've been
saying it is possible. That's because we're referring to two different
things. It is impossible in binary floating point formats to represent
exactly an arbitrary floating point value rounded to a specified number
of decimal digits. That's simply because 10 is not a power of 2. That's
what Richard was talking about.

However, it is possible to calculate a result that is as close to the
ideally rounded value as is permitted by the precision of the floating
point type, which is what I'm talking about.
>double roundto(long double value, unsigned digits)
{
long double fv=fabsl(value);
if (fv powl(10.0L,DBL_DIG) || digits DBL_DIG)
return value; // Out of range
long long p = powl(10.0L, digits);
return roundl(value * p ) / (double)p;
}

Supposing long double is extended precision, why should this not
work?

Well, it unnecessarily fails to work when digits is negative.
???
It is unsigned, how can it be negative?
I suppose
you could impose the arbitrary requirement digits >= 0, but the function
has an obvious meaning for digits<0, and that meaning is just as useful
as the meaning for digits >= 0 (which is not meant to imply that it's
particularly useful in either case).

PARSE ERROR.

Can you tell me
1) Why you want a negative rounding? What that would mean?
2) Why is not particularly useful?
Specifying that long double has extended precision is not sufficient,
even when digits>=0. A conforming implementation of C can use extended
precision for both double and long double, so long as __STDC_IEC559__ is
not #defined. In that case there's no guarantee that 'p' is big enough
to store the largest integer that can be stored in a double.
So what? This means that you will not get the best results
as with better implementations but you WILL get the BEST
result for THAT implementation.

As a
result, the rounded result will have less accuracy than it should.
Fine. Obviously we should use the standard types for longest ints
here intmax_t and not long long

Point taken.
--
jacob navia
jacob at jacob point remcomp point fr
logiciels/informatique
http://www.cs.virginia.edu/~lcc-win32
Nov 23 '07 #57
In article <fi**********@aioe.orgja***@nospam.org writes:
....
And it IS possible to round correctly a double precision
number. One of the possible solutions is:

#include <stdio.h>
#include <math.h>

void RoundMyDouble (long double *value, short numberOfPrecisions)

{
long double fv=fabsl(*value);
if (fv 1e17)
return ;
long long p = powl(10.0L, numberOfPrecisions);
*value = (long long)(*value * p + 0.5L) / (double)p;
}
This does *not* round correctly. If you round 6.123465e+23 to four
places you should get: 6.123000e+23.
--
dik t. winter, cwi, kruislaan 413, 1098 sj amsterdam, nederland, +31205924131
home: bovenover 215, 1025 jn amsterdam, nederland; http://www.cwi.nl/~dik/
Nov 23 '07 #58
In article <fi**********@aioe.orgja***@nospam.org writes:
....
double roundto(long double value, unsigned digits)
{
long double fv=fabsl(value);
if (fv powl(10.0L,DBL_DIG) || digits DBL_DIG)
return value; // Out of range
long long p = powl(10.0L, digits);
return roundl(value * p ) / (double)p;
}

Supposing long double is extended precision, why should this not
work?
Because the return of roundto(6.12345e+50, 4) should be 6.12300e+50.
--
dik t. winter, cwi, kruislaan 413, 1098 sj amsterdam, nederland, +31205924131
home: bovenover 215, 1025 jn amsterdam, nederland; http://www.cwi.nl/~dik/
Nov 23 '07 #59
James Kuyper wrote:
jacob navia wrote:
>Mark McIntyre wrote:
...
>>I copy-pasted this exact code, and compiled under gcc 4.1.2:

thelinux clc_tests $ ./a.out 0.33
1374389535.0000000000000000000: 0 decimals 1374389535.0000000000000000
1374389535.0000000000000000000: 1 decimals 1374389535.0000000000000000

I'm giving this one a 'strange' score of 'high'

Yes, because stdlib.h is missing. You need it for the prototype of atof.
You saw the warning and then you spread nonsense, like all
your posts.

Why was it missing?
In lcc-win wasn't missing since it is in stdlib.h
--
jacob navia
jacob at jacob point remcomp point fr
logiciels/informatique
http://www.cs.virginia.edu/~lcc-win32
Nov 23 '07 #60
jacob navia wrote:
James Kuyper wrote:
>jacob navia wrote:
...
>>This is perfectly OK since double has only 16 decimal digits,
and the first ones in your result appear at 1e-21 (if I counted

Citation please? Where does the C standard impose such requirements
for all implementations?

I changed my function to use DBL_DIG already. See elsethread
Your program assumes that long long is guaranteed to be sufficiently
large to store the longest integer representable as a double. The use
you made of DBL_DIG doesn't cover the problems that can occur if that
assumption is false, as it is allowed to be for conforming
implementations of C which do not #define __STDC_IEC559__.

When are you planning on acknowledging that point? I'm getting pretty
tire of typing the name of that macro.
Nov 23 '07 #61
Marco Manfredini wrote:
jacob navia wrote:
>Marco Manfredini wrote:
>>Richard Heathfield wrote:
jacob navia said:

Richard Heathfield wrote:
>Could someone else please share with us the result they get when they
>drive this function with inputs of 0.33 and 1 ? I'm getting some
>very,
>very strange results here.
>>
d:\lcc\mc68\test>type tdouble3.c

No, I said "someone else". I wouldn't trust you to make a cup of
coffee, let alone a computer program.

long double roundto(long double value, unsigned digits)
{

This is not my function excuse me.

My function returned a double, NOT a long double.

AND THAT IS IMPORTANT!

Yes, for your demonstration, because double gracefully removes the cruft
from the end of your "rounded" value and printf does the rest.
We are speaking (read the subject line please) of "Rounding double"

OK????

I have said many times already that to round to double precision
you use higher precision then you round as the last step!

I am not speaking about rounding of long double that is a much
more difficult problem. And please do not CHANGE MY function and
then accuse ME of not being honest!
--
jacob navia
jacob at jacob point remcomp point fr
logiciels/informatique
http://www.cs.virginia.edu/~lcc-win32
Nov 23 '07 #62
Dik T. Winter wrote:
In article <fi**********@aioe.orgja***@nospam.org writes:
...
double roundto(long double value, unsigned digits)
{
long double fv=fabsl(value);
if (fv powl(10.0L,DBL_DIG) || digits DBL_DIG)
return value; // Out of range
long long p = powl(10.0L, digits);
return roundl(value * p ) / (double)p;
}
>
Supposing long double is extended precision, why should this not
work?

Because the return of roundto(6.12345e+50, 4) should be 6.12300e+50.
This is nonsense. We are speaking of rounding to some place AFTER the
decimal point here!
--
jacob navia
jacob at jacob point remcomp point fr
logiciels/informatique
http://www.cs.virginia.edu/~lcc-win32
Nov 23 '07 #63
Dik T. Winter wrote:
In article <fi**********@aioe.orgja***@nospam.org writes:
...
And it IS possible to round correctly a double precision
number. One of the possible solutions is:
>
#include <stdio.h>
#include <math.h>
>
void RoundMyDouble (long double *value, short numberOfPrecisions)
>
{
long double fv=fabsl(*value);
if (fv 1e17)
return ;
long long p = powl(10.0L, numberOfPrecisions);
*value = (long long)(*value * p + 0.5L) / (double)p;
}

This does *not* round correctly. If you round 6.123465e+23 to four
places you should get: 6.123000e+23.
No, we speak about places AFTER the decimal point

--
jacob navia
jacob at jacob point remcomp point fr
logiciels/informatique
http://www.cs.virginia.edu/~lcc-win32
Nov 23 '07 #64
In article <Jr********@cwi.nl"Dik T. Winter" <Di********@cwi.nlwrites:
....
This does *not* round correctly. If you round 6.123465e+23 to four
places you should get: 6.123000e+23.
Sorry, I was wrong.
--
dik t. winter, cwi, kruislaan 413, 1098 sj amsterdam, nederland, +31205924131
home: bovenover 215, 1025 jn amsterdam, nederland; http://www.cwi.nl/~dik/
Nov 23 '07 #65
jacob navia wrote, On 22/11/07 23:35:
Mark McIntyre wrote:
>jacob navia wrote:
>>This is perfectly OK since double has only 16 decimal digits,

This is incorrect. The ISO standard requires a double to have at least
10 digits, but specifies no upper bound.

5.2.4.2.2 Characteristics of floating types
8. The values given in the following list shall be replaced by
constant expressions with implementation-defined values that are
greater or equal in magnitude (absolute value) to those shown, with
the same sign:
FLT_DIG 6
DBL_DIG 10
LDBL_DIG 10

There are a couple of worked examples showing 15 digits, and one
footnote that references the ISO/IEC floating point standard, but
nothing else normative.

That "footnote" is Annex F, and it IS normative. I cite (again)

F.2 Types
1 The C floating types match the IEC 60559 formats as follows:
— The float type matches the IEC 60559 single format.
— The double type matches the IEC 60559 double format
Now read the introduction to the Annex again, specifically the part that
says "An implementation that defines __STDC_IEC_559__ shall conform to
the specifications in this annex." Then note the conditional in that
statement which makes the entire annex optional. Something that has
already been pointed out to you.

Here are some references to show it has been pointed out to you
http://groups.google.com/group/comp....345b4f241c0201
http://groups.google.com/group/comp....2a58ce536d7ddb
http://groups.google.com/group/comp....39c3b8f11ad83d

That is just a few of the occasions it has been pointed out just in case
the posts in this thread pointing it out have failed to reach you.
--
Flash Gordon
Nov 23 '07 #66
jacob navia wrote:
>
I have said many times already that to round to double precision
you use higher precision then you round as the last step!

I am not speaking about rounding of long double that is a much
more difficult problem. And please do not CHANGE MY function and
then accuse ME of not being honest!

If I take your original routine I get:
0.3333333332999999787382705562777118757367

using a long double return I get:
0.3333333332999999999886331369935987822828

So basically you are saying, your kludge works by converting a value
with a smaller error into a result with a *larger error*. You are hoping
that the current rounding mode does the cleanup, that's all. This is
extremely fragile.

Nov 23 '07 #67
jacob navia wrote:
James Kuyper wrote:
....
>I suppose you could impose the arbitrary requirement digits >= 0, but
the function has an obvious meaning for digits<0, and that meaning is
just as useful as the meaning for digits >= 0 (which is not meant to
imply that it's particularly useful in either case).


PARSE ERROR.

Can you tell me
1) Why you want a negative rounding? What that would mean?
digits== 2 indicates rounding to the nearest multiple of 10^-2==0.01
digits== 1 indicates rounding to the nearest multiple of 10^-1==0.1
digits== 0 indicates rounding to the nearest multiple of 10^0==1.0
digits==-1 would indicate rounding to the nearest multiple of 10^1==10.
digits==-2 would indicate rounding to the nearest multiple of 10^2==100
etc.

It isn't even difficult to modify your algorithm to handle this case.
Please slow down and think more about your messages before posting them.
You're missing some pretty obvious points due to overly rushed posting.
2) Why is not particularly useful?
Because rounding to a specified number of decimal digits makes sense
almost exclusive for character string outputs, and the printf() family
of functions already handles that part of the task quite well.
>Specifying that long double has extended precision is not sufficient,
even when digits>=0. A conforming implementation of C can use extended
precision for both double and long double, so long as __STDC_IEC559__
is not #defined. In that case there's no guarantee that 'p' is big
enough to store the largest integer that can be stored in a double.

So what? This means that you will not get the best results
as with better implementations but you WILL get the BEST
result for THAT implementation.
No, my point was that if 'p' is not big enough to store the longest
integer that can be stored in a double, you will get a result that is
less precise than the best you can get on THAT implementation. That's
because use of 'long long' as an intermediate is not the only possible
way to do it, and some of the other ways allow you to get the full
maximum accuracy.
>As a result, the rounded result will have less accuracy than it should.

Fine. Obviously we should use the standard types for longest ints
here intmax_t and not long long
Not needed. If you bother thinking about the hints I dropped, it should
be quite obvious how to perform the task without using any integer type
bigger than int.
Nov 23 '07 #68
jacob navia wrote, On 23/11/07 00:00:
James Kuyper wrote:
>jacob navia wrote:
>>James Kuyper wrote:
jacob navia wrote:
James Kuyper wrote:
>jacob navia wrote:
>>James Kuyper wrote:
>...
>>Probably. Your solution is always the best since you did not
>>propose any
>>
>?
>I suggesting using sprintf() and sscanf(). I left the details to
>be worked out by the reader. Was that too obscure a hint for you?
>
But he was asking for a function that returns a double, not
asking about PRINTING a double.

OK - so my hint WAS too obscure. Think about it a little while
before you respond again. I'm sure you can figure it out with a
little extra thought. In particular, think about the implications
of the fact that I specified sprintf() rather than printf(), and
sscanf() instead of scanf().

Have you given any more thought to my hint? If not, why did you quote it?

Note: Richard Heathfield has been saying this is impossible, I've been
saying it is possible. That's because we're referring to two different
things. It is impossible in binary floating point formats to represent
exactly an arbitrary floating point value rounded to a specified
number of decimal digits. That's simply because 10 is not a power of
2. That's what Richard was talking about.

However, it is possible to calculate a result that is as close to the
ideally rounded value as is permitted by the precision of the floating
point type, which is what I'm talking about.
At least your solution has a correct intermediate result, although the
final result could well be inaccurate as you acknowledge.
>>double roundto(long double value, unsigned digits)
{
long double fv=fabsl(value);
if (fv powl(10.0L,DBL_DIG) || digits DBL_DIG)
return value; // Out of range
long long p = powl(10.0L, digits);
return roundl(value * p ) / (double)p;
}

Supposing long double is extended precision, why should this not
work?

Well, it unnecessarily fails to work when digits is negative.

???
It is unsigned, how can it be negative?
Where did the OP specify only a positive number?
>I suppose you could impose the arbitrary requirement digits >= 0, but
the function has an obvious meaning for digits<0, and that meaning is
just as useful as the meaning for digits >= 0 (which is not meant to
imply that it's particularly useful in either case).


PARSE ERROR.

Can you tell me
1) Why you want a negative rounding? What that would mean?
Tell me to the nearest million what your sales figures are for the last
year...
2) Why is not particularly useful?
Because if you are doing further arithmetic on the number you have
errors and if not you can just output it to the correct number of digits.
>Specifying that long double has extended precision is not sufficient,
even when digits>=0. A conforming implementation of C can use extended
precision for both double and long double, so long as __STDC_IEC559__
is not #defined. In that case there's no guarantee that 'p' is big
enough to store the largest integer that can be stored in a double.

So what? This means that you will not get the best results
as with better implementations but you WILL get the BEST
result for THAT implementation.
double and long double could be exactly the same, or long long could be
too small.
>As a result, the rounded result will have less accuracy than it should.

Fine. Obviously we should use the standard types for longest ints
here intmax_t and not long long
Which still might not be long enough.
Point taken.
You still need more work to understand the problems.
--
Flash Gordon
Nov 23 '07 #69
jacob navia wrote, On 23/11/07 00:01:
James Kuyper wrote:
>jacob navia wrote:
>>Mark McIntyre wrote:
...
>>>I copy-pasted this exact code, and compiled under gcc 4.1.2:

thelinux clc_tests $ ./a.out 0.33
1374389535.0000000000000000000: 0 decimals 1374389535.0000000000000000
1374389535.0000000000000000000: 1 decimals 1374389535.0000000000000000

I'm giving this one a 'strange' score of 'high'
Yes, because stdlib.h is missing. You need it for the prototype of atof.
You saw the warning and then you spread nonsense, like all
your posts.

Why was it missing?

In lcc-win wasn't missing since it is in stdlib.h
Your original code posted here did not include stdlib.h, it started:
--------------------
d:\lcc\mc68\test>type tdouble3.c
#include <stdio.h>
#include <float.h>
#include <math.h>

double roundto(long double value, unsigned digits)
--------------------
The above is a direct copy and paste from your post.
--
Flash Gordon
Nov 23 '07 #70
Dik T. Winter wrote:
In article <fi**********@aioe.orgja***@nospam.org writes:
...
double roundto(long double value, unsigned digits)
{
long double fv=fabsl(value);
if (fv powl(10.0L,DBL_DIG) || digits DBL_DIG)
return value; // Out of range
long long p = powl(10.0L, digits);
return roundl(value * p ) / (double)p;
}
>
Supposing long double is extended precision, why should this not
work?

Because the return of roundto(6.12345e+50, 4) should be 6.12300e+50.
I think the OP was talking about the number of digits after the decimal
point in %f format, not in %e format.
Nov 23 '07 #71
jacob navia wrote:
James Kuyper wrote:
>jacob navia wrote:
>>Mark McIntyre wrote:
...
>>>I copy-pasted this exact code, and compiled under gcc 4.1.2:

thelinux clc_tests $ ./a.out 0.33
1374389535.0000000000000000000: 0 decimals 1374389535.0000000000000000
1374389535.0000000000000000000: 1 decimals 1374389535.0000000000000000

I'm giving this one a 'strange' score of 'high'
Yes, because stdlib.h is missing. You need it for the prototype of atof.
You saw the warning and then you spread nonsense, like all
your posts.

Why was it missing?

In lcc-win wasn't missing since it is in stdlib.h
I wasn't asking why atof was missing, I was asking why

#include <stdlib.h>

was missing.
Nov 23 '07 #72
jacob navia wrote:
Walter Roberson wrote:
>jacob navia <ja***@nospam.orgwrote:
>>Richard Heathfield wrote:
jacob navia said:
>>>>Who cares?
>>>People who don't wish to mislead to OP by giving incorrect advice.
>>Incorrect advice happens only when they read your posts.

Incorrect advice also happens when people read some of *my* posts,
so your "only" would appear to be incorrect.

I don't know of -any- poster here who has a perfect advice posting
record (though some average much higher quality than others.)

And there are others that do not give ANY solution, limiting
themselves to say why the solutions presented in some cases not
asked for would not work

I used the original solution and fixed it for double precision,
< it is surely not the best solution.
>
But instead of proposing a better solution this people limit
to talking nonsense without ever proposing anything else.

Then I get angry start getting mad at heathfield and this
degrades.
No, you didn't propose a better solution. You proposed a solution
that is invalid on all the newsgroups posted (long since snipped),
and thoroughly off-topic. You then objected to being corrected.

--
Chuck F (cbfalconer at maineline dot net)
<http://cbfalconer.home.att.net>
Try the download section.

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

Nov 23 '07 #73
jacob navia wrote:
Mark McIntyre wrote:
.... snip ...
>
>I'm giving this one a 'strange' score of 'high'

Yes, because stdlib.h is missing. You need it for the prototype
of atof. You saw the warning and then you spread nonsense, like
all your posts.
Oh well done. Someone responds to your post, and you then come
back with a nasty dig, thus gaining many friends in the newsgroup.
You really needed that final sentence.

--
Chuck F (cbfalconer at maineline dot net)
<http://cbfalconer.home.att.net>
Try the download section.
--
Posted via a free Usenet account from http://www.teranews.com

Nov 23 '07 #74
Richard Heathfield wrote:
jacob navia said:
.... snip ...
>
>And it IS possible to round correctly a double precision number.

Show me 0.33 rounded to one decimal place.
Hunh? How about:

double r = 0.33, s;

s = (int)((r * 10.0) + 0.5) / 10.0;

which, according to me, gives the desired value in s within the
accuracy limits of doubles. I suspect it might even work for C++.
:-)

--
Chuck F (cbfalconer at maineline dot net)
<http://cbfalconer.home.att.net>
Try the download section.

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

Nov 23 '07 #75
CBFalconer said:
Richard Heathfield wrote:
>jacob navia said:
... snip ...
>>
>>And it IS possible to round correctly a double precision number.

Show me 0.33 rounded to one decimal place.

Hunh? How about:

double r = 0.33, s;

s = (int)((r * 10.0) + 0.5) / 10.0;

which, according to me, gives the desired value in s within the
accuracy limits of doubles.
On my system, it gives 0.299999999999999988898, which doesn't even get the
first digit right.

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Nov 23 '07 #76
Mark McIntyre said:
jacob navia wrote:
>>Could someone else please share with us the result they get when they
drive this function with inputs of 0.33 and 1 ? I'm getting some very,
very strange results here.
>d:\lcc\mc68\test>type tdouble3.c

I copy-pasted this exact code, and compiled under gcc 4.1.2:

thelinux clc_tests $ ./a.out 0.33
1374389535.0000000000000000000: 0 decimals 1374389535.0000000000000000
1374389535.0000000000000000000: 1 decimals 1374389535.0000000000000000

I'm giving this one a 'strange' score of 'high'
Thanks, Mark, for doing that. I used the exact same code, except that I
read ahead in the thread and added <stdlib.has a result (I didn't get a
warning about atof because I had to switch off many diagnostics to get the
code to compile at all), and I also had to put braces around the last two
lines of roundto. I'm getting the following results:

me@here./foo 0.33
0.3300000000000000155: 0 decimals 256.0000000000000000
0.3300000000000000155: 1 decimals -21474836.0000000000000000
0.3300000000000000155: 2 decimals -20468203.0000000000000000
0.3300000000000000155: 3 decimals -1522532.0000000000000000
0.3300000000000000155: 4 decimals -83414.0000000000000000
0.3300000000000000155: 5 decimals -21322.0000000000000000
0.3300000000000000155: 6 decimals -1591.0000000000000000
0.3300000000000000155: 7 decimals -91.0000000000000000
0.3300000000000000155: 8 decimals 0.0000000000000000
0.3300000000000000155: 9 decimals -1.0000000000000000
0.3300000000000000155: 10 decimals 0.0000000000000000
0.3300000000000000155: 11 decimals 0.0000000000000000
0.3300000000000000155: 12 decimals 0.0000000000000000
0.3300000000000000155: 13 decimals 0.0000000000000000
0.3300000000000000155: 14 decimals 0.0000000000000000

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Nov 23 '07 #77
Richard Heathfield wrote:
Mark McIntyre said:
>jacob navia wrote:
>>>Could someone else please share with us the result they get when they
drive this function with inputs of 0.33 and 1 ? I'm getting some very,
very strange results here.
d:\lcc\mc68\test>type tdouble3.c
I copy-pasted this exact code, and compiled under gcc 4.1.2:

thelinux clc_tests $ ./a.out 0.33
1374389535.0000000000000000000: 0 decimals 1374389535.0000000000000000
1374389535.0000000000000000000: 1 decimals 1374389535.0000000000000000

I'm giving this one a 'strange' score of 'high'

Thanks, Mark, for doing that. I used the exact same code, except that I
read ahead in the thread and added <stdlib.has a result (I didn't get a
warning about atof because I had to switch off many diagnostics to get the
code to compile at all), and I also had to put braces around the last two
lines of roundto. I'm getting the following results:

me@here./foo 0.33
0.3300000000000000155: 0 decimals 256.0000000000000000
0.3300000000000000155: 1 decimals -21474836.0000000000000000
0.3300000000000000155: 2 decimals -20468203.0000000000000000
0.3300000000000000155: 3 decimals -1522532.0000000000000000
0.3300000000000000155: 4 decimals -83414.0000000000000000
0.3300000000000000155: 5 decimals -21322.0000000000000000
0.3300000000000000155: 6 decimals -1591.0000000000000000
0.3300000000000000155: 7 decimals -91.0000000000000000
0.3300000000000000155: 8 decimals 0.0000000000000000
0.3300000000000000155: 9 decimals -1.0000000000000000
0.3300000000000000155: 10 decimals 0.0000000000000000
0.3300000000000000155: 11 decimals 0.0000000000000000
0.3300000000000000155: 12 decimals 0.0000000000000000
0.3300000000000000155: 13 decimals 0.0000000000000000
0.3300000000000000155: 14 decimals 0.0000000000000000
Have you any idea why this is happening? I got none of the warnings you
complained about (using -std=c99 -pedantic -W -Wall) and the results
seem to be what Jacob gets. (Of course, if he has invoked UB this means
nothing.)

I do find it ironic that Jacob insists the problem is soluble, but even
after using his rounding he /still/ uses your proposed solution of using
printf() to round on output...

pgp@medusa-s2:~/tmp$ gcc -std=c99 -pedantic -W -Wall -lm jn.c -ojn
jn.c:16: warning: unused parameter 'argc'
pgp@medusa-s2:~/tmp$ ./jn 0.33
0.3300000000000000155: 0 decimals 0.0000000000000000
0.3300000000000000155: 1 decimals 0.3000000000000000
0.3300000000000000155: 2 decimals 0.3300000000000000
0.3300000000000000155: 3 decimals 0.3300000000000000
0.3300000000000000155: 4 decimals 0.3300000000000000
0.3300000000000000155: 5 decimals 0.3300000000000000
0.3300000000000000155: 6 decimals 0.3300000000000000
0.3300000000000000155: 7 decimals 0.3300000000000000
0.3300000000000000155: 8 decimals 0.3300000000000000
0.3300000000000000155: 9 decimals 0.3300000000000000
0.3300000000000000155: 10 decimals 0.3300000000000000
0.3300000000000000155: 11 decimals 0.3300000000000000
0.3300000000000000155: 12 decimals 0.3300000000000000
0.3300000000000000155: 13 decimals 0.3300000000000000
0.3300000000000000155: 14 decimals 0.3300000000000000

I'm disappointed with the misleading results here which suggest that the
LHS has trailing cruft which the RHS doesn't, when both have such cruft.
Nov 23 '07 #78
Philip Potter said:
Richard Heathfield wrote:
<snip>
>I used the exact same code, except that I
read ahead in the thread and added <stdlib.has a result (I didn't get
a warning about atof because I had to switch off many diagnostics to get
the code to compile at all), and I also had to put braces around the
last two lines of roundto. I'm getting the following results:

me@here./foo 0.33
0.3300000000000000155: 0 decimals 256.0000000000000000
0.3300000000000000155: 1 decimals -21474836.0000000000000000
0.3300000000000000155: 2 decimals -20468203.0000000000000000
[...]
>
Have you any idea why this is happening?
Well, obviously I don't have a C99 compiler (I use gcc, which doesn't
conform to C99 yet), so to avoid changing the code too much I am forced to
rely on gcc extensions (which is why I had to turn off my usual collection
of diagnostic switches). It is possible that one or more of the extensions
don't operate according to C99 rules.

<snip>
I do find it ironic that Jacob insists the problem is soluble, but even
after using his rounding he /still/ uses your proposed solution of using
printf() to round on output...
This rapid accretion of irony over many such threads over several years has
now formed a solid irony cory so large that its gravityy is now having a
significant effect; not only has it attracted a lot of crusty, but it even
appears to have acquired an atmosphery.

<snip>
I'm disappointed with the misleading results here which suggest that the
LHS has trailing cruft which the RHS doesn't, when both have such cruft.
It's all down to smoke and mirrors.

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Nov 23 '07 #79
Philip Potter wrote:
Richard Heathfield wrote:
[snip]
I'm getting the following results:
>>
me@here./foo 0.33
0.3300000000000000155: 0 decimals 256.0000000000000000
0.3300000000000000155: 1 decimals -21474836.0000000000000000
0.3300000000000000155: 2 decimals -20468203.0000000000000000
0.3300000000000000155: 3 decimals -1522532.0000000000000000
0.3300000000000000155: 4 decimals -83414.0000000000000000
0.3300000000000000155: 5 decimals -21322.0000000000000000
0.3300000000000000155: 6 decimals -1591.0000000000000000
0.3300000000000000155: 7 decimals -91.0000000000000000
0.3300000000000000155: 8 decimals 0.0000000000000000
0.3300000000000000155: 9 decimals -1.0000000000000000
0.3300000000000000155: 10 decimals 0.0000000000000000
0.3300000000000000155: 11 decimals 0.0000000000000000
0.3300000000000000155: 12 decimals 0.0000000000000000
0.3300000000000000155: 13 decimals 0.0000000000000000
0.3300000000000000155: 14 decimals 0.0000000000000000

Have you any idea why this is happening? I got none of the warnings you
complained about (using -std=c99 -pedantic -W -Wall) and the results
seem to be what Jacob gets. (Of course, if he has invoked UB this means
nothing.)

I do find it ironic that Jacob insists the problem is soluble, but even
after using his rounding he /still/ uses your proposed solution of using
printf() to round on output...

pgp@medusa-s2:~/tmp$ gcc -std=c99 -pedantic -W -Wall -lm jn.c -ojn
jn.c:16: warning: unused parameter 'argc'
pgp@medusa-s2:~/tmp$ ./jn 0.33
0.3300000000000000155: 0 decimals 0.0000000000000000
0.3300000000000000155: 1 decimals 0.3000000000000000
0.3300000000000000155: 2 decimals 0.3300000000000000
0.3300000000000000155: 3 decimals 0.3300000000000000
0.3300000000000000155: 4 decimals 0.3300000000000000
0.3300000000000000155: 5 decimals 0.3300000000000000
0.3300000000000000155: 6 decimals 0.3300000000000000
0.3300000000000000155: 7 decimals 0.3300000000000000
0.3300000000000000155: 8 decimals 0.3300000000000000
0.3300000000000000155: 9 decimals 0.3300000000000000
0.3300000000000000155: 10 decimals 0.3300000000000000
0.3300000000000000155: 11 decimals 0.3300000000000000
0.3300000000000000155: 12 decimals 0.3300000000000000
0.3300000000000000155: 13 decimals 0.3300000000000000
0.3300000000000000155: 14 decimals 0.3300000000000000

I'm disappointed with the misleading results here which suggest that the
LHS has trailing cruft which the RHS doesn't, when both have such cruft.
1: This is because I forgot in the format specifier of the LHS to
imit to DBL_DIG.
2: As you can see, my solution works in your machine. Either RH is not
telling the truth (unlikely) or he is using some minor error in the
code to trip about.
3: It is interesting to note that you say that my solution doesn't
work when you see correct results in your machine.

--
jacob navia
jacob at jacob point remcomp point fr
logiciels/informatique
http://www.cs.virginia.edu/~lcc-win32
Nov 23 '07 #80
jacob navia said:

<snip>
2: As you can see, my solution works in your machine. Either RH is not
telling the truth (unlikely) or he is using some minor error in the
code to trip about.
If your code has an error, however minor, then it is broken, in which case
I suggest you post a fixed version. The version you posted *does not work*
on my system. Quite apart from the fact that you are trying to solve an
impossible problem (the problem, remember, is that of rounding the value
of a double to a specified number of decimal places, which simply can't be
done), you are trying to solve it in a way that produces bizarrely
incorrect results on at least one system.

And no, I didn't make those results up.

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Nov 23 '07 #81
Richard Heathfield wrote:
jacob navia said:

<snip>
>2: As you can see, my solution works in your machine. Either RH is not
telling the truth (unlikely) or he is using some minor error in the
code to trip about.

If your code has an error, however minor, then it is broken, in which case
I suggest you post a fixed version. The version you posted *does not work*
on my system. Quite apart from the fact that you are trying to solve an
impossible problem (the problem, remember, is that of rounding the value
of a double to a specified number of decimal places, which simply can't be
done), you are trying to solve it in a way that produces bizarrely
incorrect results on at least one system.

And no, I didn't make those results up.
Since you provide no information on which compilation options
you used, no information on which system you are running, this
can't be solved really.

And if I have a minor error somewhere correct it instead
of just spreading FUD

--
jacob navia
jacob at jacob point remcomp point fr
logiciels/informatique
http://www.cs.virginia.edu/~lcc-win32
Nov 23 '07 #82
jacob navia <ja***@nospam.comwrites:
Richard Heathfield wrote:
>jacob navia said:

<snip>
>>2: As you can see, my solution works in your machine. Either RH is not
telling the truth (unlikely) or he is using some minor error in the
code to trip about.

If your code has an error, however minor, then it is broken, in
which case I suggest you post a fixed version. The version you
posted *does not work* on my system. Quite apart from the fact that
you are trying to solve an impossible problem (the problem,
remember, is that of rounding the value of a double to a specified
number of decimal places, which simply can't be done), you are
trying to solve it in a way that produces bizarrely incorrect
results on at least one system.

And no, I didn't make those results up.

Since you provide no information on which compilation options
you used, no information on which system you are running, this
can't be solved really.

And if I have a minor error somewhere correct it instead
of just spreading FUD
So that would be the "minor error in the code to trip about" option from
RH then. Good to see nothing much changes with regard to his superiority
complex.

Nov 23 '07 #83
jacob navia said:

<snip>
Since you provide no information on which compilation options
you used, no information on which system you are running, this
can't be solved really.
The compilation options shouldn't matter, but I'll tell you anyway:

gcc -o foo foo.c -lm

If the system matters, then presumably you agree that your code is not
portable C, and specify on which systems or classes of system you expect
your code to work. But I'll tell you anyway: AMD Athlon XP1600+ running at
1.4GHz.
And if I have a minor error somewhere correct it instead
of just spreading FUD
The correction is easy:

rm foo.c

del foo.c

....or whatever local command does the equivalent (i.e. delete the source
file).

I recommend this correction to the OP, since the program you posted
completely fails to solve the original problem that he posed. It can't be
corrected for the simple reason that the problem as stated cannot be
solved, as I have already pointed out several times in this thread.

And no, I'm not spreading FUD. Fear doesn't enter into it, and there is no
doubt, no uncertainty, whatsoever that your code does *not* solve the
problem stated by the OP. It attempts to solve a different problem, and
does so in a non-portable manner (because otherwise I'd get the same
results that you do).

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Nov 23 '07 #84
Richard Heathfield wrote:
jacob navia said:

<snip>
>2: As you can see, my solution works in your machine. Either RH is not
telling the truth (unlikely) or he is using some minor error in the
code to trip about.

If your code has an error, however minor, then it is broken, in which case
I suggest you post a fixed version. The version you posted *does not work*
on my system. Quite apart from the fact that you are trying to solve an
impossible problem (the problem, remember, is that of rounding the value
of a double to a specified number of decimal places, which simply can't be
done), you are trying to solve it in a way that produces bizarrely
incorrect results on at least one system.
Hm. I wonder if this might be a matter of interpreting the problem.

The C standard says about sqrt() that it computed the nonnegative square
root. C++ inherits this requirement. If your interpretation of the rounding
problem is correct and if we transfer it to the other arithmetic
operations, then there can be no conforming implementations. In fact, even
elementary school arithmetic (+,-,*,/) cannot be done correctly under that
interpretation. However, that interpretation of the specs is not the only
possible.

A different interpretation of floating point computations is that an
operation (say multiplication, addition, sqrt, or rounding to a given
number of decimal places) should yield a double (or float or whatever types
are topical in the corresponding newsgroup) that is closest to the exact
mathematical result. If I recall correctly, this is by and large the
position taken by IEEE754.

When this (reasonable) interpretation is adopted, the problem of rounding to
a fixed number of decimals is solvable (and it is indeed not different from
any other computational problem). And if you don't adopt an interpretation
like that, floating point arithmetic in general is "impossible".
Best

Kai-Uwe Bux
Nov 23 '07 #85
Kai-Uwe Bux wrote:
Richard Heathfield wrote:
>jacob navia said:

<snip>
>>2: As you can see, my solution works in your machine. Either RH is not
telling the truth (unlikely) or he is using some minor error in the
code to trip about.
If your code has an error, however minor, then it is broken, in which case
I suggest you post a fixed version. The version you posted *does not work*
on my system. Quite apart from the fact that you are trying to solve an
impossible problem (the problem, remember, is that of rounding the value
of a double to a specified number of decimal places, which simply can't be
done), you are trying to solve it in a way that produces bizarrely
incorrect results on at least one system.

Hm. I wonder if this might be a matter of interpreting the problem.

The C standard says about sqrt() that it computed the nonnegative square
root. C++ inherits this requirement. If your interpretation of the rounding
problem is correct and if we transfer it to the other arithmetic
operations, then there can be no conforming implementations. In fact, even
elementary school arithmetic (+,-,*,/) cannot be done correctly under that
interpretation. However, that interpretation of the specs is not the only
possible.
I am arguing precisely this since the beginning of this thread.
All trascendental functions, sqrt, pow, whatever. All of them yield
approximations of their real results.

The solution I proposed is surely not the best one but it is a first
try after a summary discussion here.

A different interpretation of floating point computations is that an
operation (say multiplication, addition, sqrt, or rounding to a given
number of decimal places) should yield a double (or float or whatever types
are topical in the corresponding newsgroup) that is closest to the exact
mathematical result. If I recall correctly, this is by and large the
position taken by IEEE754.
EXACTLY.
When this (reasonable) interpretation is adopted, the problem of rounding to
a fixed number of decimals is solvable (and it is indeed not different from
any other computational problem). And if you don't adopt an interpretation
like that, floating point arithmetic in general is "impossible".
Best

Kai-Uwe Bux

This is exactly my position.

--
jacob navia
jacob at jacob point remcomp point fr
logiciels/informatique
http://www.cs.virginia.edu/~lcc-win32
Nov 23 '07 #86
jacob navia said:

<snip>
All trascendental functions, sqrt, pow, whatever. All of them yield
approximations of their real results.
Indeed, because finitely many bits cannot store the results precisely; and
this is why the OP's problem *as stated* has no solution. You are solving
a *different* problem (in a non-portable way).

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Nov 23 '07 #87
Richard Heathfield wrote:
Philip Potter said:
>Richard Heathfield wrote:

<snip>
>>I used the exact same code, except that I
read ahead in the thread and added <stdlib.has a result (I didn't get
a warning about atof because I had to switch off many diagnostics to get
the code to compile at all), and I also had to put braces around the
last two lines of roundto. I'm getting the following results:

me@here./foo 0.33
0.3300000000000000155: 0 decimals 256.0000000000000000
0.3300000000000000155: 1 decimals -21474836.0000000000000000
0.3300000000000000155: 2 decimals -20468203.0000000000000000
[...]
>Have you any idea why this is happening?

Well, obviously I don't have a C99 compiler (I use gcc, which doesn't
conform to C99 yet), so to avoid changing the code too much I am forced to
rely on gcc extensions (which is why I had to turn off my usual collection
of diagnostic switches). It is possible that one or more of the extensions
don't operate according to C99 rules.
You may have noticed I used gcc too. I have no qualms about using
-std=c99 when I know it not to be fully-conformant; it appears you do.
>I do find it ironic that Jacob insists the problem is soluble, but even
after using his rounding he /still/ uses your proposed solution of using
printf() to round on output...

This rapid accretion of irony over many such threads over several years has
now formed a solid irony cory so large that its gravityy is now having a
significant effect; not only has it attracted a lot of crusty, but it even
appears to have acquired an atmosphery.
"significanty effecty" surely? :)

Nov 23 '07 #88
jacob navia wrote:
2: As you can see, my solution works in your machine. Either RH is not
telling the truth (unlikely) or he is using some minor error in the
code to trip about.
Given that you use long long and RH doesn't have a C99 compiler and
doesn't use -std=c99 on gcc, I don't think results on his (or even my)
machine are too meaningful.
3: It is interesting to note that you say that my solution doesn't
work when you see correct results in your machine.
Er, if you're referring to this:
>I do find it ironic that Jacob insists the problem is soluble, but
even after using his rounding he /still/ uses your proposed solution
of using printf() to round on output...
...then I think it stands for itself. The reason your solution works is
because you use printf() to cut off the rounding error; RH's solution
used *exactly the same feature of printf()* to round.
Nov 23 '07 #89
Richard Heathfield wrote:
jacob navia said:
>Since you provide no information on which compilation options
you used, no information on which system you are running, this
can't be solved really.

The compilation options shouldn't matter, but I'll tell you anyway:
No, they *do* matter. gcc is not a conforming C89, C95 or C99
implementation with no compilation options. With -ansi -pedantic, it's
quite a good C89 compiler. With -std=c99 -pedantic, it's a half-finished
C99 compiler.

I'm sure you know this already.

Nov 23 '07 #90
Kai-Uwe Bux wrote:
A different interpretation of floating point computations is that an
operation (say multiplication, addition, sqrt, or rounding to a given
number of decimal places) should yield a double (or float or whatever
types are topical in the corresponding newsgroup) that is closest to
the exact mathematical result. If I recall correctly, this is by and
large the position taken by IEEE754.

When this (reasonable) interpretation is adopted, the problem of
rounding to a fixed number of decimals is solvable (and it is indeed
not different from any other computational problem). And if you don't
adopt an interpretation like that, floating point arithmetic in
general is "impossible".
The problem with rounded numbers is that they have to be exact or else
the whole rounding is pointless. Rounding is done, because you want a
number whose relative error is 1) known 2) independent of the
representation and 3) it's operations gives the same result *no matter
what implementation of arithmetic operations you are using, given that
the result remains exact and representable*. If you have a bank account
you will acknowledge this - financial applications often have very
tight specifications on *how exactly* something has to be calculated,
when rounding must be done etc.

That's entirely different from working with trancedental numbers and
such which have no known representation anyway.

And actually, the problem is solvable with floating point. Multiply and
truncate, but omit the division and store the result with the decimal
designator in a struct { double value; int places; }. Voila, an exactly
rounded number. Now define arithmetic ops and go.

--
IYesNo yes=YesNoFactory.getFactoryInstance().YES;
yes.getDescription().equals(array[0].toUpperCase());
Nov 23 '07 #91
On Nov 23, 10:29 am, Richard Heathfield <r...@see.sig.invalidwrote:
on my system. Quite apart from the fact that you are trying to solve an
impossible problem (the problem, remember, is that of rounding the value
of a double to a specified number of decimal places, which simply can't be
done)
Impossible? Rounding a floating point number to N decimals, or for
that matter any other interval such as 1/30, is possible and does have
uses other than simply printing the number.

Of course the result will be approximate because of the nature of
floating point, but will be billions of times more accurate than
doing no rounding because 'it can't be done'.

If I have a measurement X somewhere along a 1m stick (0.0 to 1.0) and
I want to find the nearest 10cm mark to X (eg X is 0.78, the nearest
will be 0.8), then it's clear than I can round 0.78 to 1 decimal (or
1/10) to get 0.8. The result, being stored in floating point binary,
may be out by a billionth of a micron or so. So what? My pencil mark
on the stick will not be that accurate.

The point is such a rounding can be done and has a useful purpose.

Bart
Nov 23 '07 #92
Richard Heathfield wrote:
jacob navia said:

<snip>
>All trascendental functions, sqrt, pow, whatever. All of them yield
approximations of their real results.

Indeed, because finitely many bits cannot store the results precisely; and
this is why the OP's problem *as stated* has no solution. You are solving
a *different* problem (in a non-portable way).
It is quite possible that the OP was unaware of the fact that the
rounding could not be performed exactly. However, you cannot justify
assuming that he had that misconception just because he failed to
specify that he wanted the best available floating point approximation
to the rounded number. Leaving out the "best available approximation
...." wording in the expectation that it would be inferred by any
reasonable reader is the norm, not the exception, in such specifications.

The OP's follow-up messages have not clarified whether or not he was
aware of that issue when he posted the original message.

Nov 23 '07 #93
Richard Heathfield wrote:
jacob navia said:

<snip>
>All trascendental functions, sqrt, pow, whatever. All of them yield
approximations of their real results.

Indeed, because finitely many bits cannot store the results precisely; and
this is why the OP's problem *as stated* has no solution. You are solving
a *different* problem (in a non-portable way).
Well, telling the OP that his problem is unsolvable "as stated" could be a
good thing. Maybe he then just decides to report back to the customer and
the customer realizes that this was a stupid thing to ask for and everybody
is happy.

Another possible reaction of the OP is to not find that reply very helpful.
Maybe, he even thinks that you did not make an honest effort to interpret
his question correctly. Why would the OP want to know how to do X if a
moments thought tells you that doing X is impossible? Well, maybe he
doesn't know enough about floating point arithmetic to tell. But, maybe the
OP is not that uneducated and just gave an abbreviated description of the
problem (very much like the C standard where it requires that sqrt shall
compute the nonnegative square root of the argument).

When someone asks a question, the goal of interpretation is to figure out
what it is that this someone wants to know. I have the feeling that your
interpretation might fall short of reaching this goal. I do concede,
though, that we do not have much to go on.

It would be great if the OP could provide some more background as to _why_
he wants to round. For instance, it could be that he needs to comply with
accounting rules in his country which may require that certain values be
rounded to n decimals when transcribed from one table into another.
Depending on the purpose, your advice of postponing the problem until
output might be the right one; or it might be that the OP needs to use
decimal arithmetic instead of double to actually solve the hidden problem.
Best

Kai-Uwe Bux
Nov 23 '07 #94
Philip Potter said:
Richard Heathfield wrote:
>jacob navia said:
>>Since you provide no information on which compilation options
you used, no information on which system you are running, this
can't be solved really.

The compilation options shouldn't matter, but I'll tell you anyway:

No, they *do* matter. gcc is not a conforming C89, C95 or C99
implementation with no compilation options. With -ansi -pedantic, it's
quite a good C89 compiler. With -std=c99 -pedantic, it's a half-finished
C99 compiler.

I'm sure you know this already.
Yes, it's a fair point. Okay, if I invoke gcc in conforming mode, the code
doesn't compile at all, for a number of reasons. (Clearly, to invoke gcc
in conforming mode means we have to go for C89 or, if you prefer, C90
conformance, since gcc doesn't have a C99 conforming mode.)

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Nov 23 '07 #95
James Kuyper wrote:
Richard Heathfield wrote:
>jacob navia said:

<snip>
>>All trascendental functions, sqrt, pow, whatever. All of them yield
approximations of their real results.

Indeed, because finitely many bits cannot store the results precisely;
and this is why the OP's problem *as stated* has no solution. You are
solving a *different* problem (in a non-portable way).

It is quite possible that the OP was unaware of the fact that the
rounding could not be performed exactly. However, you cannot justify
assuming that he had that misconception just because he failed to
specify that he wanted the best available floating point approximation
to the rounded number. Leaving out the "best available approximation
..." wording in the expectation that it would be inferred by any
reasonable reader is the norm, not the exception, in such specifications.

The OP's follow-up messages have not clarified whether or not he was
aware of that issue when he posted the original message.
In general, 100% exact results using floating point are impossible,
as you know very well.

Then, obviously, anyone asking here for the best rounding to n places
is asking for an approximation.

Suppose we get a question like:

"Please how can I calculate the square root of a number in C"

we all assume that it is about "the best floating point
approximation" and nobody would say "This problem
is impossible to solve as demonstrated by the greeks around
2000 years ago"

Nowhere did the OP say that he wanted 100% accuracy!

Now that Mr Heathfield sees that his position is completely untenable,
he starts modifying the original question, putting more words into the
OP than what he actually said.

I have argued since the beginning that the problem is solvable in
floating point in the usual floating pont manner, i.e. as an
approximation to the true result!

--
jacob navia
jacob at jacob point remcomp point fr
logiciels/informatique
http://www.cs.virginia.edu/~lcc-win32
Nov 23 '07 #96
Bart said:
On Nov 23, 10:29 am, Richard Heathfield <r...@see.sig.invalidwrote:
>on my system. Quite apart from the fact that you are trying to solve an
impossible problem (the problem, remember, is that of rounding the value
of a double to a specified number of decimal places, which simply can't
be done)

Impossible? Rounding a floating point number to N decimals, or for
that matter any other interval such as 1/30, is possible and does have
uses other than simply printing the number.
Show me.
>
Of course the result will be approximate
But rounding is an operation that yields an exact result. 0.33, rounded to
one decimal place, is *precisely* 0.3, not 0.299999999999998 or
0.300000000000001 (no, I didn't count the 9s and 0s - I just held the key
down!). If the result is not exact, it isn't a rounding. It's merely an
approximation to a rounding.
because of the nature of
floating point, but will be billions of times more accurate than
doing no rounding because 'it can't be done'.
Oh, it can be done all right - it's just that it can't be done using
floating point. More precisely, you can't store 0.33 rounded to one
decimal place in a floating point number (unless you use a radix that
makes it possible, in which case there are other numbers you can't store).

If I have a measurement X somewhere along a 1m stick (0.0 to 1.0) and
I want to find the nearest 10cm mark to X (eg X is 0.78, the nearest
will be 0.8), then it's clear than I can round 0.78 to 1 decimal (or
1/10) to get 0.8.
Right.
The result, being stored in floating point binary,
may be out by a billionth of a micron or so. So what? My pencil mark
on the stick will not be that accurate.
Indeed, but the result will still be out.
The point is such a rounding can be done and has a useful purpose.
Yes, it can, but only by adopting a different representation. A double
simply can't cut it.

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Nov 23 '07 #97
Richard Heathfield wrote:
Philip Potter said:
>Richard Heathfield wrote:
>>jacob navia said:

Since you provide no information on which compilation options
you used, no information on which system you are running, this
can't be solved really.
The compilation options shouldn't matter, but I'll tell you anyway:
No, they *do* matter. gcc is not a conforming C89, C95 or C99
implementation with no compilation options. With -ansi -pedantic, it's
quite a good C89 compiler. With -std=c99 -pedantic, it's a half-finished
C99 compiler.

I'm sure you know this already.

Yes, it's a fair point. Okay, if I invoke gcc in conforming mode, the code
doesn't compile at all, for a number of reasons. (Clearly, to invoke gcc
in conforming mode means we have to go for C89 or, if you prefer, C90
conformance, since gcc doesn't have a C99 conforming mode.)
Can you stop all this theater?

Now compile with
gcc -std=c99 jn.c -lm

and tell me the results ok?

And if you do not want it do not compile it and shut up.

--
jacob navia
jacob at jacob point remcomp point fr
logiciels/informatique
http://www.cs.virginia.edu/~lcc-win32
Nov 23 '07 #98
James Kuyper said:
Richard Heathfield wrote:
>jacob navia said:

<snip>
>>All trascendental functions, sqrt, pow, whatever. All of them yield
approximations of their real results.

Indeed, because finitely many bits cannot store the results precisely;
and this is why the OP's problem *as stated* has no solution. You are
solving a *different* problem (in a non-portable way).

It is quite possible that the OP was unaware of the fact that the
rounding could not be performed exactly.
That is my belief, yes.
However, you cannot justify
assuming that he had that misconception just because he failed to
specify that he wanted the best available floating point approximation
to the rounded number.
On the other hand, answering *all* the questions people *don't* ask would
take infinite time. We're not mind readers.

If the OP is happy to take 0.2999999999999999999999998 as the result of
rounding 0.33 to one decimal place, that's fine - but he has not (yet)
said so.

<snip>

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Nov 23 '07 #99
Marco Manfredini wrote:
Kai-Uwe Bux wrote:
>A different interpretation of floating point computations is that an
operation (say multiplication, addition, sqrt, or rounding to a given
number of decimal places) should yield a double (or float or whatever
types are topical in the corresponding newsgroup) that is closest to
the exact mathematical result. If I recall correctly, this is by and
large the position taken by IEEE754.

When this (reasonable) interpretation is adopted, the problem of
rounding to a fixed number of decimals is solvable (and it is indeed
not different from any other computational problem). And if you don't
adopt an interpretation like that, floating point arithmetic in
general is "impossible".

The problem with rounded numbers is that they have to be exact or else
the whole rounding is pointless.
A rounding rule is a function r : R --R with usually discrete image. The
possible reasons for computing that function vary. Depending on the
reasons, an IEEE754-like rounding function may or may not be fit for a
given purpose.
Rounding is done, because you want a
number whose relative error is 1) known 2) independent of the
representation and 3) it's operations gives the same result *no matter
what implementation of arithmetic operations you are using, given that
the result remains exact and representable*. If you have a bank account
you will acknowledge this - financial applications often have very
tight specifications on *how exactly* something has to be calculated,
when rounding must be done etc.
I am not sure I understand your conditions (2) and (3). However, with regard
to accounting software, you might sometimes get away with an IEEE754-like
rounding function, although I would think that it can be somewhat difficult
to prove that the output is not different from the theoretical output if
rounding was done exactly. However, in principle this is no different from
the analysis of other errors. You know that the rounding function used has
a small error compare to the mathematical rounding, and now you have to
show that this error stays small and does not influence the printed result
(here of course, you have to take into account the rounding that occurs in
printing).

That's entirely different from working with trancedental numbers and
such which have no known representation anyway.
Not as far as the numerical analysis of algorithms is concerned. However, as
a practical matter, it might be much easier to use a decimal_number class
that allows for exact rounding. This way, you are only using the basic
operations recognized by the accounting rules of the land, and you are
guaranteed that floating point arithmetic won't get you in jail.

And actually, the problem is solvable with floating point. Multiply and
truncate, but omit the division and store the result with the decimal
designator in a struct { double value; int places; }. Voila, an exactly
rounded number. Now define arithmetic ops and go.
I would think that that is one way to go about implementing a decimal_number
class.
Best

Kai-Uwe Bux
Nov 23 '07 #100

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

3 posts views Thread by Dalan | last post: by
3 posts views Thread by Norvin Laudon | last post: by
5 posts views Thread by Jason | last post: by
29 posts views Thread by Marco | last post: by
13 posts views Thread by Shirsoft | last post: by
6 posts views Thread by abcd | last post: by
5 posts views Thread by Spoon | last post: by
248 posts views Thread by md | last post: by
20 posts views Thread by jacob navia | last post: by
3 posts views Thread by gieforce | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.