Rounding double

R

Richard Heathfield

James Kuyper said:
If the only features of C99 that it uses are features that are widely
supported by compilers in their C99 modes, then the fact that those
modes are not fully conforming is not sufficient to render the code
valueless.

Indeed. That's why I said "almost valueless". :)
 
R

Richard Heathfield

James Kuyper said:
No, but we should be able to read ordinary English (and technical
English) and interpret it in conventional fashion as implying, as it
normally does, a great many unstated assumptions. Stating all applicable
assumptions would also take infinite time. Even explicitly stating only
the most important assumptions that are conventionally left unstated
would make the questions unreadable.

Then we are at the stage where the OP needs to clarify his requirements,
because it seems to me that the conventional interpretation that I and
some others here have used is diametrically opposite to your conventional
interpretation (or at least the conventional interpretation that you are
defending).
 
R

Richard Heathfield

Philip Potter said:
So? If you don't have a C compiler, you don't try a FORTRAN compiler
instead to see if it works.

Right. But you might try gcc in non-conforming mode, and that is what I
(and several other people in this thread) have done.
I know you dislike many features of C99 and also like to talk about the
lack of uptake of C99; however that is not a valid reason to compile
code which uses "long long" under C89 and complain that it doesn't work.
Of course it doesn't work, it's not C89 code!

Like others here, I used gcc in non-conforming mode in an effort to compile
the code. Anyone who claims he used gcc in *conforming* mode is mistaken,
since the code requires C99 features that are not available in any
conforming gcc mode. This is because gcc does not have a mode that
conforms to C99.
If that is your problem with Jacob's program then say so.

No, that's a side issue. The principal problem with the program is that it
does not solve the OP's problem.
The fact that
Jacob's code is broken in C89 might be something you personally dislike,
but if it works in C99 it is perfectly topical regardless of the number
of working C99 distributions in existence.

I can certainly agree with that. I have not said, and do not claim, that
the code is off-topic.
 
J

jacob navia

Richard said:
Philip Potter said:


Right. But you might try gcc in non-conforming mode, and that is what I
(and several other people in this thread) have done.

And that of course doesn't work. And instead of saying

you say:

"Jacob's code doesn't work and I get nonsense results"

Very honest.
Like others here, I used gcc in non-conforming mode in an effort to compile
the code. Anyone who claims he used gcc in *conforming* mode is mistaken,
since the code requires C99 features that are not available in any
conforming gcc mode. This is because gcc does not have a mode that
conforms to C99.

and gcc -std=c99 is wrong or what?
I can certainly agree with that. I have not said, and do not claim, that
the code is off-topic.

You were claiming that it produced nonsense results. At the end we see
that you were deliberately misusing gcc.
 
R

Richard Heathfield

jacob navia said:
And that of course doesn't work.
Right.

And instead of saying

I'd love one, actually. Do you have one?
you say:

"Jacob's code doesn't work and I get nonsense results"

Very honest.

But that *is* what I observed. I was using gcc extensions, which seems to
be what everyone else was doing too. And it is certainly true that the
code doesn't work, because it *doesn't do what was required*. The fact
that it gave weird results on my system isn't all that important, but I
was sufficiently puzzled to ask other people what results they were
getting.
and gcc -std=c99 is wrong or what?

No, it's not wrong - but it doesn't invoke a C99-conforming compiler.
Calling a switch "-std=c99" does not magically provide C99 conformance.
You were claiming that it produced nonsense results.

On my system, it did.
At the end we see that you were deliberately misusing gcc.

If you can come up with a set of switches that makes the code work on the
gcc implementation currently installed on my system, I'm all ears.
 
J

jacob navia

Richard said:
If you can come up with a set of switches that makes the code work on the
gcc implementation currently installed on my system, I'm all ears.
What is that implementation?
It must be older than 2000!

The best thing would be for you to iunstall an up to date
version.
 
B

Bart

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

If you accept the fact that such a rounding will not be exact (the
error depending partly on the magnitude of the values), then code such
as the following (modified from Jacob Navia's code posted elsewhere)
might be of use:

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

void RoundMyDouble (long double *value, short numberOfPrecisions)

{
long long p = powl(10.0L, numberOfPrecisions);
*value = floor(*value * p + 0.5L) / (double)p;
}

int main(void) /* demo */
{
long double v = 3.1415926535897932384626L;
short int ndp = 0;
while(ndp < 20)
{
long double newv = v;
RoundMyDouble(&newv, ndp);
printf("%.21Lf, \"rounded\" to %hd decimals, is %.21Lf\n",
(v),
ndp++,
newv);
}

return 0;
}

With this code, rounding a value such as 5.288123 to 3 decimals (for
which you would expect 5.288) might actually produce 5.287999999... or
5.2880000000...044 or whatever. Whatever it is, it will be the best
approximation to 5.288. Printing this to a limited number of decimals
should display 5.288000... however)

(In fact reading "5.288" into a double you will run into the same
problem.

If accuracy is essential, and you are rounding to 4 decimals for
example, then multiply by 10000 and work with integers, or doubles
containing integral values.

Bart
 
R

Richard Heathfield

jacob navia said:
What is that implementation?
2.95.3

It must be older than 2000!

So? It still works just fine with properly written, portable code.
The best thing would be for you to iunstall an up to date
version.

Why? So that I can compile a misconceived non-solution to an insoluble
problem? I don't see the point.

When GNU finally get a conforming C99 implementation together, that'll be
worth an upgrade. Until then, I see no reason to break a working system.
(We have seen quite recently that there are versions of gcc later than
2.95.3 that incorporate exciting new bugs not present in the older version
- but I don't need that kind of excitement.)
 
K

Keith Thompson

Kai-Uwe Bux said:
> Richard Heathfield wrote:
>
>
> Hm. I wonder if this might be a matter of interpreting the problem.

Yes, I think it is.
> 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.

Right. The C standard (if __STDC_IEC_559__ is not #defined) imposes
weaker requirements; the result of the sqrt() function needn't be the
*closest* to the exact mathematical result. In fact, I don't think the
C standard imposes any accuracy requirements at all. I'm not certain
that an implementation with sqrt(2.0)==1.5 would be non-conforming.
It's a quality issue, and such an implementation of sqrt() would be
considered badly broken because it would be useless, not because it's
necessarily non-conforming.

But that's largely beside the point, which is that the standard
operators and functions on floating-point are not expected to yield
exact results, because they can't.
> 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".

But there's a fundamental difference between sqrt() and a function
that purports to round a floating-point value to a specified number
of decimal places.

For the sqrt() function, obtaining a close approximation to the
mathematical result is obviously a useful thing to do. There are
some contexts in which you might want to throw up your hands and
say "Sorry, it's not possible to compute sqrt(2.0) exactly" -- but
obtaining a close approximation is both useful and expected.

For the rounding function, sure, you could write a function that,
given arguments (3.14159, 2) would return the closest floating-point
approximation of the mathematical value 3.14. But it's not at all
clear either that this would be useful, or that it's really what the
original poster wants.

Either (A) the OP really wants the exact result, and wasn't aware
that it's impossible, or (B) the OP wants an approximate result, and
wasn't aware that it's not particularly useful, or (C) the OP wants
an approximate result, and knows that it's actually useful to him
for some reason that none of us can figure out and he hasn't chosen
to share with us.

My guess is that (A) is the most likely scenario. I speculate that
the OP wants to take a floating-point value with lots of significant
digits after the decimal point, convert it to a value with fewer
significant digits after the decimal point (e.g., 3.14159 --> 3.14),
and use that value for textual output. If so, he has almost certainly
asked the wrong question; what he really do is pass the full-precision
value directly to printf, and use printf's own facilities to round
the textual output, not the number. (Substitite sprintf or fprintf
as needed.)

Some posters in this thread have been wasting a great deal of time
trying to provide incomplete and incorrect answers to what the OP
asked, rather than trying to determine what the OP really needs.

Yes, I think it's a matter of interpreting the problem. Leaving
aside my blind speculation above, the only way to do this is for the
original poster to *tell us* how we should interpret the problem.
Perhaps he's daunted by the volume of replies, but there should be
enough information buried in this mega-thread for him to figure out
how to ask the right question, or at least to discuss how to figure
out how to ask the right question. Until and less the OP returns
and helps us out, all we're doing here is correcting each other's
errors (which is important, but doesn't help the OP nearly as much
as avoiding those errors in the first place would have).
 
M

Mark McIntyre

jacob said:
That "footnote" is Annex F, and it IS normative.

I don't disagree. Please read what I wrote more carefully.

You may also want to reread annex F, and note that the entire annex is
optional. Did you think that an annex would explicitly contradict an
earlier chapter, and nobody noticed before?
 
M

Mark McIntyre

Flash said:
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 gather you've worked with the Japanese central bank. :)
 
M

Mark McIntyre

jacob said:
Yes, because stdlib.h is missing. You need it for the prototype of atof.

Oh, I see - its MY fault that you posted nonsense code, and claimed it
worked.
Perhaps you want to gang an bile yer heid, ye great plooter?
 
M

Mark McIntyre

Philip said:
Richard Heathfield wrote:

:) I found it far more amusing to compile the precise code posted.
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.

Quite - if you print 'em both to 19dp...

mark@thelinux clc_tests $ ./a.out 0.33
0.3300000000000000155: 0 decimals 0.0000000000000000000
0.3300000000000000155: 1 decimals 0.2999999999999999889
0.3300000000000000155: 2 decimals 0.3300000000000000155
0.3300000000000000155: 3 decimals 0.3300000000000000155

I especially like the second answer.
 
J

jacob navia

Mark said:
Oh, I see - its MY fault that you posted nonsense code, and claimed it
worked.
Perhaps you want to gang an bile yer heid, ye great plooter?

I got tired of #including math.h and finding out that atof
wasn't there but in stdlib.h. So I put it in math.h in lcc-win.
This is of course not the case with gcc, that has it in stdlib.

This minor flaw doesn't make all the code "nonsense" as you
say. Just keep calm
 
M

Mark McIntyre

Richard said:
Well, obviously I don't have a C99 compiler (I use gcc, which doesn't
conform to C99 yet),

In fact version 4.1.2 (I'm using it Fedora Core 6 which is at least a
year old now) supports c99 quite well. Might be worth upgrading?
 
M

Mark McIntyre

jacob navia wrote:

(nothing of substance)

oh look. Another interminable thread in which Jacob insists he's right,
and everybody else, irrespective of pedigree, learning and training, is
wrong. Nobody but him knows how to invoke their compiler properly.
Nobody knows how floating point works. etc etc etc

What a boring person.
 
P

Philip Potter

jacob said:
I got tired of #including math.h and finding out that atof
wasn't there but in stdlib.h. So I put it in math.h in lcc-win.
This is of course not the case with gcc, that has it in stdlib.

This minor flaw doesn't make all the code "nonsense" as you
say. Just keep calm

Perhaps people would keep calmer if you didn't accuse them of "spreading
nonsense".
 
F

Flash Gordon

jacob navia wrote, On 23/11/07 23:26:
I got tired of #including math.h and finding out that atof
wasn't there but in stdlib.h. So I put it in math.h in lcc-win.
This is of course not the case with gcc, that has it in stdlib.

I trust that you don't do that in conforming mode, because if you do
then your compiler does not conform. Personally I would say it was
better not to do it at all and learn to use the language properly.
This minor flaw doesn't make all the code "nonsense" as you
say. Just keep calm

Ah, so code that invokes undefined behaviour and as a result fails
drastically only has a minor flaw. That is useful to know.
 
I

Ian Collins

jacob said:
I got tired of #including math.h and finding out that atof
wasn't there but in stdlib.h. So I put it in math.h in lcc-win.
This is of course not the case with gcc, that has it in stdlib.
Which is where it belongs, it isn't a math function, it is a string
conversion function.
 
G

Gordon Burditt

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.

None of the floating-point numbers printed here can be represented
exactly in binary floating point, except zero. For debugging
purposes, I recommend a better output format, say %300.200f ,
enough to ensure that you can have enough digits to exactly represent
the number you get as a result (this is quite a bit more than
FLT_DIG, DBL_DIG, or LDBL_DIG, as appropriate to the type being
used). Or perhaps someone is using base-10 floating point.
 

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

No members online now.

Forum statistics

Threads
473,995
Messages
2,570,230
Members
46,819
Latest member
masterdaster

Latest Threads

Top