Thread: Argh, division doesn't work sometimes! Check this out...

  1. #1
    Magically delicious LuckY's Avatar
    Join Date
    Oct 2001
    Posts
    856

    Question Argh, division doesn't work sometimes! Check this out...

    Okay, someone answer me this...
    I feel like I am in the twilight zone. I have very simple arithmetic here, yet the compiler generates different results for some odd reason!
    Basically I am dividing 731961 by 365.25 and the result should be exactly 2004 (no decimal). Here's some code:
    Code:
      unsigned x = 731961; 
      int y = 365;
      std::cout << "\n" << x << " / " << (y + .25) << " = " << 
        int(x / (y + .25));  
    ////////////////////////////////////////
    // what the eff???
      std::cout << "\n-->" << x << " / " << (y + .25) << " = " << 
        int(x / (365 + .25));  
      std::cout << "\n-->" << x << " / " << (y + .25) << " = " << 
        int(x / (DPY + .25));
    ////////////////////////////////////////
      std::cout << "\n" << x << " / " << (y + .25) << " = " << 
        int(731961 / (y + .25));  
      std::cout << "\n" << x << " / " << (y + .25) << " = " << 
        int(731961 / (365 + .25));  
      std::cout << "\n" << x << " / " << (y + .25) << " = " << 
        int(731961 / (DPY + .25));
    This outputs this:
    731961 / 365.25 = 2004
    -->731961 / 365.25 = 2003
    -->731961 / 365.25 = 2003
    731961 / 365.25 = 2004
    731961 / 365.25 = 2004
    731961 / 365.25 = 2004
    Do you have any effin clue why this is happening???? Argh!

  2. #2
    Magically delicious LuckY's Avatar
    Join Date
    Oct 2001
    Posts
    856
    Equivalently baffling:

    I ran this and it worked fine (result was 2004):
    Code:
    unsigned x = 731961; int y = 365;
    std::cout << "\n" << x << " / " << (y + .25) << " = " << int(x / (y + .25)) << std::endl;
    Then I ran this and it resulted in 2003:
    Code:
    unsigned x = 731961; static const int y = 365;
    std::cout << "\n" << x << " / " << (y + .25) << " = " << int(x / (y + .25)) << std::endl;
    [edit]
    I also wanted to point out another twilight zone deal.
    I have a member variable called _daycount. In a member function, I'm doing this:
    // _daycount contains 731961
    _daycount / 365.25
    and it is returning 2003, again, instead of 2004 (this is origin of my problems).. Just pointing out that in the previous examples, the denominator was the problem, but in this case it's the numerator..

    I am just about to cry... If you can help at all, please do
    Last edited by LuckY; 03-26-2003 at 10:47 AM.

  3. #3
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    That's pretty cool. What compiler/version are you two using? I always get 2004 in VC++ 6.0.

    gg

  4. #4
    Magically delicious LuckY's Avatar
    Join Date
    Oct 2001
    Posts
    856
    Borland C++ 5.5.1

    Pretty cool? hehe.. Yeah, if it's not your problem ;P

    I suppose I could simply switch over to MSVC, but it's a library I'm writing and I'd really like it to work independent of the compiler. It does appear to be a compiler issue, but it is quite strange since I've never heard of or experienced such issues in the past.
    Quite disturbing... ugh.

  5. #5
    Magically delicious LuckY's Avatar
    Join Date
    Oct 2001
    Posts
    856
    While I appreciate the sentiment, I am well acquainted with the manner in which floating point numbers are handled. To quote myself, since you quoted only a portion of my statement,
    >I am dividing 731961 by 365.25 and the result should be exactly 2004 (no decimal)
    Note the "no decimal" part. I wasn't referring to the way in which the computer was handling any truncation. Rather, I was stating that the mathematical statement 731961 / 365.25 is equivalent to 2004 (according to a calculator, iow).
    The reason for the different answers between
    std::cout << "\n" << x << " / " << (y + .25) << " = " <<
    int(x / (y + .25));

    and

    std::cout << "\n-->" << x << " / " << (y + .25) << " = " <<
    int(x / (365 + .25));

    is basically the way in which the various parts are promoted.
    While at first there seems to be some validity to this idea, in all reality it doesn't make a difference in the end result. I have even declared y as a double, but it yielded the same results. Aside from that, as CodePlug mentioned, in MSVC the results were as they should be. Furthermore, were that the case, the following two lines would also evaluate to different values:
    Code:
      std::cout << "\n" << x << " / " << (y + .25) << " = " << 
        int(731961 / (y + .25));  
      std::cout << "\n" << x << " / " << (y + .25) << " = " << 
        int(731961 / (365 + .25));

  6. #6
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    I found some interresting stuff on http://www.eskimo.com/~scs/C-faq/top.html
    14.1: When I set a float variable to, say, 3.1, why is printf printing
    it as 3.0999999?

    A: Most computers use base 2 for floating-point numbers as well as
    for integers. In base 2, one divided by ten is an infinitely-
    repeating fraction (0.0001100110011...), so fractions such as
    3.1 (which look like they can be exactly represented in decimal)
    cannot be represented exactly in binary. Depending on how
    carefully your compiler's binary/decimal conversion routines
    (such as those used by printf) have been written, you may see
    discrepancies when numbers (especially low-precision floats) not
    exactly representable in base 2 are assigned or read in and then
    printed (i.e. converted from base 10 to base 2 and back again).
    See also question 14.6.
    ...
    14.4: My floating-point calculations are acting strangely and giving
    me different answers on different machines.

    A: First, see question 14.2 above.

    If the problem isn't that simple, recall that digital computers
    usually use floating-point formats which provide a close but by
    no means exact simulation of real number arithmetic. Underflow,
    cumulative precision loss, and other anomalies are often
    troublesome.

    Don't assume that floating-point results will be exact, and
    especially don't assume that floating-point values can be
    compared for equality. (Don't throw haphazard "fuzz factors"
    in, either; see question 14.5.)

    These problems are no worse for C than they are for any other
    computer language. Certain aspects of floating-point are
    usually defined as "however the processor does them" (see also
    question 11.34), otherwise a compiler for a machine without the
    "right" model would have to do prohibitively expensive
    emulations.

    This article cannot begin to list the pitfalls associated with,
    and workarounds appropriate for, floating-point work. A good
    numerical programming text should cover the basics; see also the
    references below.

    References: Kernighan and Plauger, _The Elements of Programming
    Style_ Sec. 6 pp. 115-8; Knuth, Volume 2 chapter 4; David
    Goldberg, "What Every Computer Scientist Should Know about
    Floating-Point Arithmetic".
    ...
    14.13: I'm having trouble with a Turbo C program which crashes and says
    something like "floating point formats not linked."

    A: Some compilers for small machines, including Borland's
    (and Ritchie's original PDP-11 compiler), leave out certain
    floating point support if it looks like it will not be needed.
    In particular, the non-floating-point versions of printf()
    and scanf() save space by not including code to handle %e, %f,
    and %g. It happens that Borland's heuristics for determining
    whether the program uses floating point are insufficient,
    and the programmer must sometimes insert a dummy call to a
    floating-point library function (such as sqrt(); any will
    do) to force loading of floating-point support. (See the
    comp.os.msdos.programmer FAQ list for more information.)
    Notice the reference which Salem already posted

    I would be interrested in knowing if the workaround in 14.13 solves the problem. If that doesn't work, see if explicitly casting the denominator to double works, ie. double(y + .25).

    gg

    [EDIT]
    And casting both numerator and denominator....
    Last edited by Codeplug; 03-26-2003 at 12:07 PM.

  7. #7
    Skunkmeister Stoned_Coder's Avatar
    Join Date
    Aug 2001
    Posts
    2,572
    The simple answer is to use integer calculations. Floting point to integer and back again after calcs done is hardly braintaxing stuff!
    Free the weed!! Class B to class C is not good enough!!
    And the FAQ is here :- http://faq.cprogramming.com/cgi-bin/smartfaq.cgi

  8. #8
    Magically delicious LuckY's Avatar
    Join Date
    Oct 2001
    Posts
    856
    see if explicitly casting the denominator to double works, ie. double(y + .25).
    [EDIT]
    And casting both numerator and denominator....
    I already tried that... And that, but neither works

    The simple answer is to use integer calculations. Floting point to integer and back again after calcs done is hardly braintaxing stuff!
    For being a stoner, you are right on the ball... I don't know why I'm being such a lamebrain! I already had to do such a thing to perform a modulus operation, yet I totally lacked the brain power to dig that fact up for this mofo. Hehe. Thanks for pointing out the obvious (you would think), Stonethrower. I guess the surprising way in which the compiler was acting just threw me right off the ball...

    Thanks again to all and to all a good night.
    Last edited by LuckY; 03-26-2003 at 12:46 PM.

  9. #9
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    Did you try the work around listed in "14.13" of the quote I posted?

    gg

  10. #10
    Confused Magos's Avatar
    Join Date
    Sep 2001
    Location
    Sweden
    Posts
    3,145
    Originally posted by Salem
    > Basically I am dividing 731961 by 365.25 and the result should be exactly 2004
    There are no exacts when it comes to floating point. Floating point numbers are approximations, so mathematical answers (the correct ones) are sometimes different from the computational answers (the ones you have to live with).
    But both 731961 and 365.25 can be expressed correctly in floating point numbers (assuming they follow the IEEE standard).
    MagosX.com

    Give a man a fish and you feed him for a day.
    Teach a man to fish and you feed him for a lifetime.

  11. #11
    Magically delicious LuckY's Avatar
    Join Date
    Oct 2001
    Posts
    856
    SparkPlug,
    I did attempt to fix it using the suggestion in that article, alas, to no avail...

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. BN_CLICKED, change button style
    By bennyandthejets in forum Windows Programming
    Replies: 13
    Last Post: 07-05-2010, 11:42 PM
  2. how to put a check on an extern variable set as flag
    By rebelsoul in forum C Programming
    Replies: 18
    Last Post: 05-25-2009, 03:13 AM
  3. MFC check box question
    By MyglyMP2 in forum Windows Programming
    Replies: 2
    Last Post: 03-09-2009, 05:47 PM
  4. writing/reading from file produces double results.
    By stumon in forum C Programming
    Replies: 4
    Last Post: 03-20-2003, 04:01 PM
  5. check my code ( if statement, file existance )
    By Shadow in forum C Programming
    Replies: 1
    Last Post: 10-04-2001, 11:13 AM