Ceil double problem

  • Thread starter mikael.liljeroth
  • Start date
M

mikael.liljeroth

Why do I get NO as result from this ??

double du = (double)3.1415;
du = ceil(du);
if(du == (double)4)
printf("YES\n");
else
printf("NO\n");
 
V

Vladimir S. Oka

Why do I get NO as result from this ??

double du = (double)3.1415;
du = ceil(du);
if(du == (double)4)
printf("YES\n");
else
printf("NO\n");

I get YES (mingw/gcc). Your machine may not be able to represent 4.0
exactly. Your implementation of `ceil()` may be broken. Have you
included <math.h>? Did you try to print out `du` before and after
`ceil()`? I may have missed some other possibilities...
 
K

Keith Thompson

Why do I get NO as result from this ??

double du = (double)3.1415;
du = ceil(du);
if(du == (double)4)
printf("YES\n");
else
printf("NO\n");

I don't know. I'd expect it to print YES, and it did so when I
compiled your code -- but only after I put it into an actual program.

You've posted a code fragment, not a program, so strictly speaking it
doesn't produce any output at all.

The only explanation I can think of is that your actual program
doesn't have the required "#include <math.h>". This could cause the
compiler to assume that ceil() returns an int rather than a double,
resulting in undefined behavior.

If you still haven't figured it out, post a complete compilable
program that reproduces the problem.

Incidentally, the casts are unnecessary. A floating-point literal
such as 3.1415 is already of type float; in the comparison, it's
simpler and cleaner to use "4.0" rather than "(double)4)".
 
R

Richard Bos

Vladimir S. Oka said:
Not if it uses bas 3 arithmetic. ;-)
Do doubles have to be encoded in base 2?

Oddly enough, no. Or rather, oddly enough, the base doesn't have to be a
power of 2; base 16 FP maths would be reasonable on some systems.
However, DBL_DIG must be greater than or equal to 10; 4.0 only has 1
decimal.

Richard
 
K

Keith Thompson

Vladimir S. Oka said:
Not if it uses bas 3 arithmetic. ;-)
Do doubles have to be encoded in base 2?

Even in base 3, 4.0 is represented as 11.0. All small integer values
should be exactly representable in any sane floating-point
representation. (This is something of a circular definition [*],
since I wouldn't consider any representation that doesn't do this to
be "sane".)

Floating-point equality comparison is fraught with peril, but I would
expect it to work properly for simple values like 4.0, as long as the
value 4.0 is derived (as it is here) without any inexact operations.

[*] See "definition, circular".
 
V

Vladimir S. Oka

Keith said:
Vladimir S. Oka said:
Not if it uses bas 3 arithmetic. ;-)
Do doubles have to be encoded in base 2?

Even in base 3, 4.0 is represented as 11.0. All small integer values
should be exactly representable in any sane floating-point
representation. (This is something of a circular definition [*],
since I wouldn't consider any representation that doesn't do this to
be "sane".)

Floating-point equality comparison is fraught with peril, but I would
expect it to work properly for simple values like 4.0, as long as the
value 4.0 is derived (as it is here) without any inexact operations.

You are, of course, right. I didn't really think this through.

It'd still be interesting to know why OP's implementation failed to do
this properly.
 
J

Jordan Abel

Oddly enough, no. Or rather, oddly enough, the base doesn't have to be a
power of 2; base 16 FP maths would be reasonable on some systems.
However, DBL_DIG must be greater than or equal to 10; 4.0 only has 1
decimal.

DBL_DIG doesn't mandate an exact representation, it only requires that
all numbers to that precision be uniquely representable.

My c89 draft says:

* number of decimal digits of precision, $left floor~(p~-~1)~times~{
log sub 10 } b~right floor ~+~ left { lpile { 1 above 0 } ~~ lpile {
roman "if " b roman " is a power of 10" above roman otherwise }$

According to my best interpretation of eqn syntax, that becomes:

* number of decimal digits of precision, floor((p-1)*log[10]b)+(1 if b
is a power of 10, 0 otherwise)

neqn+nroff mangles this into (blank lines removed)

* number of decimal digits of precision, |_(_\bp-1)xlog10_\bb_|+{
is a power of 10 0
\b\b\b\b\botherwise

Where 'p' is DBL_MANT_DIG and 'b' is FLT_RADIX.
 
J

Jordan Abel

Incidentally, the casts are unnecessary. A floating-point literal
such as 3.1415 is already of type float; in the comparison, it's
simpler and cleaner to use "4.0" rather than "(double)4)".

Well, it's actually of type double. Of course, your point is still made.

A literal of type float ends in 'f'. say, 3.142f
 
J

Joe Wright

Why do I get NO as result from this ??

double du = (double)3.1415;
du = ceil(du);
if(du == (double)4)
printf("YES\n");
else
printf("NO\n");
Allow me..

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

int main(void)
/*
{
double du = (double) 3.1415;
du = ceil(du);
if (du == (double) 4)
printf("YES\n");
else
printf("NO\n");
return 0;
}
*/
{
double du = 3.1415;
du = ceil(du);
if (du == 4.0)
printf("YES\n");
else
printf("NO\n");
return 0;
}

The first instance (commented out) produces YES. The second instance
without annoying casts also produces YES. What are you doing or not
doing that produces NO?
 
K

Keith Thompson

Jordan Abel said:
Well, it's actually of type double. Of course, your point is still made.

A literal of type float ends in 'f'. say, 3.142f

You're right of course. I *meant* double, and I was sure I had
written double, but it became "float" somewhere between my brain and
my keyboard. Thanks.
 
C

CBFalconer

Joe said:
Allow me..

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

int main(void)
/*
{
double du = (double) 3.1415;
du = ceil(du);
if (du == (double) 4)
printf("YES\n");
else
printf("NO\n");
return 0;
}
*/
{
double du = 3.1415;
du = ceil(du);
if (du == 4.0)
printf("YES\n");
else
printf("NO\n");
return 0;
}

The first instance (commented out) produces YES. The second instance
without annoying casts also produces YES. What are you doing or not
doing that produces NO?

I'm giving 2 : 1 odds he didn't bother to #include <math.h>. He
then cleverly concealed this by posting only a portion of his code,
thus avoiding immediate sensible answers.

Here's the key to my other car, which is at home. It won't start
when I turn the key. Why?

--
"If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers." - Keith Thompson
More details at: <http://cfaj.freeshell.org/google/>
Also see <http://www.safalra.com/special/googlegroupsreply/>
 
D

Dik T. Winter

>
> Oddly enough, no. Or rather, oddly enough, the base doesn't have to be a
> power of 2; base 16 FP maths would be reasonable on some systems.
> However, DBL_DIG must be greater than or equal to 10; 4.0 only has 1
> decimal.

But this does *not* imply that 4.0 is exactly representable. It only
tells something about conversion and backconversion to and from a
decimal representation.
 
M

Micah Cowan

Dik T. Winter said:
But this does *not* imply that 4.0 is exactly representable. It only
tells something about conversion and backconversion to and from a
decimal representation.

I think it does, indirectly. In that, there is not a legal (integer>2)
radix in which 4.0 could not be exactly represented, if there are
enough digits in the significand to meet the DBL_DIG
requirement, and the range of possible exponents is as demanded
by the standard.

-Micah
 
J

Jordan Abel

Oops. Sorry, of course I meant >= 2, or >1. Obviously, 2 is an obvious
choice on many platforms.

I didn't see that, I was questioning that it had to be an integer. and,
not, say, e.
5.2.4.2.2#1.

Ah. I was looking at the definition of FLT_RADIX itself - i'd missed
that. It's not clear that c89 says this, though it was probably
intended.
 
D

Dik T. Winter

>
> I think it does, indirectly. In that, there is not a legal (integer>2)
> radix in which 4.0 could not be exactly represented, if there are
> enough digits in the significand to meet the DBL_DIG
> requirement, and the range of possible exponents is as demanded
> by the standard.

I do not think so. The standard (at least C89) does not require the
actual implemented floating-point arithmetic to follow the model.
The model is only used to explain the constants, if the actual
implementation is different, appropriate constants must be given.
As the footnote tells us:
"The floating-point model is intended to clarify the description of
each floating-point characteristic and does not require the
floating-point arithmetic of the implementation to be identical."
 
M

Micah Cowan

Dik T. Winter said:
I do not think so. The standard (at least C89) does not require the
actual implemented floating-point arithmetic to follow the model.
The model is only used to explain the constants, if the actual
implementation is different, appropriate constants must be given.
As the footnote tells us:
"The floating-point model is intended to clarify the description of
each floating-point characteristic and does not require the
floating-point arithmetic of the implementation to be identical."

Recall that footnotes are not normative, however.

In any case, I think the intention of that foot note is to remind us
that floating point arithmetic is merely "as-if" it followed that
model.

In any case, I don't think that the standard meant to allow
non-integer bases, or it wouldn't have made the point in disallowing
them. Given that fact, and the fact that representing 4.0 only
requires at most 2 significand digits (only base 3 requires more than
1) and an exponent value of at most 2 (only for base 2: 3 and 4
require 1, all others can use 0), I don't see how you can make
even a theoretical case for a conforming floating-point implementation
that can fail to represent it.
 

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,744
Messages
2,569,483
Members
44,901
Latest member
Noble71S45

Latest Threads

Top