Rounding double

J

jacob navia

Mark said:
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.
 
J

jacob navia

James said:
jacob navia wrote:
...

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

I changed my function to use DBL_DIG already. See elsethread
 
J

James Kuyper

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.
 
J

James Kuyper

jacob said:
Mark McIntyre wrote: ....

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?
 
M

Marco Manfredini

jacob said:
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.
 
J

jacob navia

James said:
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.


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.
 
J

James Kuyper

jacob said:
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.
 
J

jacob navia

Marco said:
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!
 
J

jacob navia

Dik said:
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!
 
J

jacob navia

Dik said:
Now, are we really such a C "heads" that we can't answer the OP
question IN HIS terms?

You discarded the solution of James Kuyper out of hand. Did you even
think about that solution?
double roundto(double d,int digits);

double roundto(double d, int digits) {
char number[digits+10];
sprintf(number, "%.*e", (digits > 0 ? digits - 1 : 0), d);
sscanf(number, "%f", &d);
return d;
}

Or somesuch.

But that is just using my function internally within
printf!
 
J

jacob navia

Dik said:
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
 
D

Dik T. Winter

> In article said:
> > Now, are we really such a C "heads" that we can't answer the OP
> > question IN HIS terms?
>
> You discarded the solution of James Kuyper out of hand. Did you even
> think about that solution?
>
> > double roundto(double d,int digits);
>
> double roundto(double d, int digits) {
> char number[digits+10];
> sprintf(number, "%.*e", (digits > 0 ? digits - 1 : 0), d);
> sscanf(number, "%f", &d);
> return d;
> }
>
> Or somesuch.

Yes, it is wrong. I missed the "after the decimal point" part. Should
be changed to use a %f format specifier in sprintf, and a few other
changes.
 
F

Flash Gordon

jacob navia wrote, On 22/11/07 23:35:
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 deï¬nes __STDC_IEC_559__ shall conform to
the speciï¬cations 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...c/20345b4f241c0201?lnk=st&q=#20345b4f241c0201
http://groups.google.com/group/comp...6/872a58ce536d7ddb?lnk=st&q=#872a58ce536d7ddb
http://groups.google.com/group/comp...f/9639c3b8f11ad83d?lnk=st&q=#9639c3b8f11ad83d

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.
 
F

Flash Gordon

jacob navia wrote, On 22/11/07 23:40:
OK from a teaching viewpoint maybe.

From very real and practical perspectives it is also not possible.
But there IS a general solution
within a double precision framework.

No, not to meet the stated requirements there is not.
Of course due to the
nature of FP it is an approximation but so what? That is
floating point and there is no way around it.

Yes, that is the situation with floating point, but many people do NOT
know this, so pretending there is an exact solution will just lead to
problems.
Instead of saying "Impossible" we should give the best
approximation that is all.

That attitude leads to a lot of bugs and a lot of problems. For all you
know the OP could be intending to round calculated currency values to
the nearest penny and then adding millions of them up and expecting an
exact result. Yes, there are *real* situations where you will get
complaints for an error of 1 penny in a result in the 10s of millions.

I.e. without knowing what the OP wants to achieve the ONLY correct
advice is that the problem as stated cannot be solved, so the OP needs
to go back to the drawing board and work out something that can be achieved.
 
M

Marco Manfredini

jacob said:
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.
 
J

James Kuyper

jacob said:
James Kuyper wrote: ....


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.
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.
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.
 
F

Flash Gordon

jacob navia wrote, On 23/11/07 00:01:
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)
 
F

Flash Gordon

jacob navia wrote, On 23/11/07 00:00:
At least your solution has a correct intermediate result, although the
final result could well be inaccurate as you acknowledge.
???
It is unsigned, how can it be negative?

Where did the OP specify only a positive number?
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.
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.
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.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,995
Messages
2,570,230
Members
46,818
Latest member
Brigette36

Latest Threads

Top