Ceil double problem

Discussion in 'C Programming' started by mikael.liljeroth, Mar 2, 2006.

  1. Why do I get NO as result from this ??

    double du = (double)3.1415;
    du = ceil(du);
    if(du == (double)4)
    mikael.liljeroth, Mar 2, 2006
    1. Advertisements

  2. 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...
    Vladimir S. Oka, Mar 2, 2006
    1. Advertisements

  3. 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)".
    Keith Thompson, Mar 2, 2006
  4. mikael.liljeroth

    Richard Bos Guest

    If so, it's broken.

    Richard Bos, Mar 2, 2006
  5. Not if it uses bas 3 arithmetic. ;-)
    Do doubles have to be encoded in base 2?
    Vladimir S. Oka, Mar 2, 2006
  6. mikael.liljeroth

    Richard Bos Guest

    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

    Richard Bos, Mar 2, 2006
  7. 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".
    Keith Thompson, Mar 2, 2006
  8. 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.
    Vladimir S. Oka, Mar 2, 2006
  9. mikael.liljeroth

    Jordan Abel Guest

    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

    Where 'p' is DBL_MANT_DIG and 'b' is FLT_RADIX.
    Jordan Abel, Mar 2, 2006
  10. mikael.liljeroth

    Jordan Abel Guest

    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
    Jordan Abel, Mar 2, 2006
  11. mikael.liljeroth

    Joe Wright Guest

    Allow me..

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

    int main(void)
    double du = (double) 3.1415;
    du = ceil(du);
    if (du == (double) 4)
    return 0;
    double du = 3.1415;
    du = ceil(du);
    if (du == 4.0)
    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?
    Joe Wright, Mar 3, 2006
  12. 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.
    Keith Thompson, Mar 3, 2006
  13. mikael.liljeroth

    CBFalconer Guest

    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/>
    CBFalconer, Mar 3, 2006
  14. 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.
    Dik T. Winter, Mar 3, 2006
  15. mikael.liljeroth

    Micah Cowan Guest

    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 Cowan, Mar 3, 2006
  16. mikael.liljeroth

    Jordan Abel Guest

    Chapter and verse.
    Jordan Abel, Mar 3, 2006
  17. mikael.liljeroth

    Micah Cowan Guest

    Oops. Sorry, of course I meant >= 2, or >1. Obviously, 2 is an obvious
    choice on many platforms.
    Micah Cowan, Mar 3, 2006
  18. mikael.liljeroth

    Jordan Abel Guest

    I didn't see that, I was questioning that it had to be an integer. and,
    not, say, e.
    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
    Jordan Abel, Mar 3, 2006
  19. 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."
    Dik T. Winter, Mar 7, 2006
  20. mikael.liljeroth

    Micah Cowan Guest

    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

    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.
    Micah Cowan, Mar 7, 2006
    1. Advertisements

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 (here). After that, you can post your question and our members will help you out.