Thread: Why does conditional (t == ZERO) always evaluate to false?

  1. #1
    Registered User
    Join Date
    Oct 2012
    Posts
    19

    Why does conditional (t == ZERO) always evaluate to false?

    What's wrong with my conditional that causes it to always evaluates to false (execute the else block)?
    Code:
    if (t == ZERO) ...
    In main, t is declared as realtype, and ZERO is defined using a macro RCONST:
    Code:
    #define ZERO  RCONST(0.0)
    realtype reltol, abstol, t, tout;
    realtype and RCONST are declared in a package. realtype​ is either float, double, or long double. In the current installation, realtype is a long double.

    RCONST is to be used to for all floating point constants so that they are declared the same way as realtype:
    Code:
    #if defined(SUNDIALS_SINGLE_PRECISION)
    ...
    #elif defined(SUNDIALS_DOUBLE_PRECISION)
    ...
    #elif defined(SUNDIALS_EXTENDED_PRECISION)
    typedef long double realtype;
    # define RCONST(x) x##L
    #endif
    t's value is zero (I confirmed that in gdb). I've tried several forms of the conditional, but all have failed (actually, they all work correctly, but they all evaluate to false):
    Code:
    if (t == ZERO) ...
    if (t == 0) ...
    if (t == 0.0) ...
    if (t == 0.0L) ...
    All of those executed the else statement, even when t is zero. Pretty obviously the second one will not work right.
    Code:
    printf("%4.0Lf\t", t);
    if (t == 0.0L) {
      printf("THEN");
    } else {
      printf("ELSE");
    }
    Output:
    0 ELSE ...
    100 ELSE ...
    200 ELSE ...
    ...
    So, what's wrong with my conditional that causes it to always evaluates to false (execute the else block), even when t is zero?​ How do I make this work right?

    Thanks.

  2. #2
    Registered User
    Join Date
    Sep 2012
    Posts
    357
    Instead of
    Code:
    printf("%4.0Lf\t", t);
    Try
    Code:
    printf("%Lf\t", t);
    Also turn on all warnings your compiler can produce, and mind the warnings.

  3. #3
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    Guess what, if it fails to give a result of true when compared as equal to zero then it is not zero. It's just not, trust me. We've come across this multiple times before.

    Now that you know beyond a doubt that the value is not zero, start looking into why everything else seems to be mistakenly telling you otherwise.
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  4. #4
    Registered User
    Join Date
    Oct 2012
    Posts
    19
    Are you telling me to print like that because it will give me a clue or because it's good programming? This is tabular output, so I can only use this to gather information. The result of changing the print is
    0.000000 ELSE ...
    which indicates that t is exactly zero.

    Currently, I'm not getting any compiler warnings. I'm not completely sure what I'm doing, but I changed the make file to compile with option -O3, (that's a capital letter "O" three). I did not get any compiler warnings. Is that the most warnings (I'm using Linux and gcc) can produce?
    Code:
    /usr/local/mpi/bin/mpicc  -Wall -g -O3            -I/home/myname/sundials/instdir/include -I/usr/local/mpi/bin/../include -c FPU.c
    /usr/local/mpi/bin/mpicc -o FPU FPU.o  -Wall -g -O3               -L/home/myname/sundials/instdir/lib -lsundials_cvode -lsundials_nvecparallel -lm  -L/usr/local/mpi/bin/../lib
    Unfortunately, I'm still stumped.

  5. #5
    Registered User
    Join Date
    Sep 2012
    Posts
    357
    Oops ... I meant
    Code:
    printf("%Lg", t);
    with a 'g' rather than an 'f', sorry.

    And, yes. That will print the number starting with the most significative digit.

    Code:
    #include <stdio.h>
    
    int main(void) {
      long double x = 0.1;
      while (x > 1E-20) {
        printf("%4.0Lf %Lf %Lg\n", x, x, x);
        x /= 10;
      }
      return 0;
    }
    And the output is

    0 0.100000 0.1
    0 0.010000 0.01
    0 0.001000 0.001
    0 0.000100 0.0001
    0 0.000010 1e-05
    0 0.000001 1e-06
    0 0.000000 1e-07
    0 0.000000 1e-08
    0 0.000000 1e-09
    0 0.000000 1e-10
    0 0.000000 1e-11
    0 0.000000 1e-12
    0 0.000000 1e-13
    0 0.000000 1e-14
    0 0.000000 1e-15
    0 0.000000 1e-16
    0 0.000000 1e-17
    0 0.000000 1e-18
    0 0.000000 1e-19
    0 0.000000 1e-20

  6. #6
    Registered User
    Join Date
    Oct 2012
    Posts
    19
    Yup, t was not equal to exactly zero. I'm not completely sure why (still a newbie!), but I have the code working now.
    P.S. I like your posting style - give hints and let me find it. (It just feels better to find it yourself!)

  7. #7
    Registered User
    Join Date
    Oct 2012
    Posts
    19
    Quote Originally Posted by iMalc View Post
    Guess what, if it fails to give a result of true when compared as equal to zero then it is not zero. It's just not, trust me. We've come across this multiple times before.

    Now that you know beyond a doubt that the value is not zero, start looking into why everything else seems to be mistakenly telling you otherwise.
    Thanks, iMalc. I wasn't sure if the issue was the conditional or the value (actually, I thought the conditional was the problem). I'm still new to C.
    Last edited by uncreativename; 10-25-2012 at 01:00 PM.

  8. #8
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    Some light reading about how floating point works on computers:
    What Every Computer Scientist Should Know About Floating-Point Arithmetic

    You know how values are stored in binary right? Each bit adds a power of two to the answer. It's the same for fractional values, except that the powers of two are negative. i.e. the first bit after the decimal point has avalue of 1/2, the next 1/4, the next 1/8 etc.
    This means that it's impossible to represent certain decimal numbers exactly. Trying to represent 1/10th in binary for example, is like trying to represent 1/7th in decimal. You'd need an infinite number of bits.
    Additionally, floating point works like scientific notation in that some bits are set aside for storing another number that tells where the decimal point is.

    The bottom line is that even adding 0.1 and 0.9 in C does not give you an answer exactly equal to 1.0. So often you don't want to compare against exact values, but instead compare within a certain margin of error of your desired value.
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. PROBLEM W/ EVALUATE....plz help me!
    By vIp3rS in forum C Programming
    Replies: 5
    Last Post: 03-04-2010, 05:00 AM
  2. Evaluate time in C++
    By nghoanglinh223 in forum C++ Programming
    Replies: 14
    Last Post: 04-02-2008, 04:51 PM
  3. Evaluate me...
    By vasanth in forum A Brief History of Cprogramming.com
    Replies: 2
    Last Post: 10-21-2003, 09:26 AM
  4. Evaluate !(1 && !(0 || 1)).
    By Grumpy_Old_Man in forum C++ Programming
    Replies: 7
    Last Post: 08-18-2003, 01:28 PM
  5. does not evaluate to a function - anyone know why?
    By rc7j in forum C++ Programming
    Replies: 5
    Last Post: 11-05-2001, 10:34 AM