LinuxQuestions.org
Review your favorite Linux distribution.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 01-10-2008, 03:31 PM   #1
h/w
Senior Member
 
Registered: Mar 2003
Location: New York, NY
Distribution: Debian Testing
Posts: 1,286

Rep: Reputation: 46
C compare double


Here's something new to me in GCC; a double comparison isn't straight-forward, or at least it doesn't seem to me from my test:

Code:
int simple(double fv, double pv, double r, double t) {
  printf("in simp\n");
  printf("fv = %lf\n", fv);
  printf("pv = %lf\n", pv);
  printf("r = %lf\n", r);
  printf("t = %lf\n", t);

  if(0.0 == fv) {
    printf("Finding FV\n");
  } else if(0.0 == pv) {
    printf("Finding PV\n");
  } else if(0.0 == r) {
    printf("Finding R\n");
  } else if(0.0 == t) {
    printf("Finding T\n");
  } else {
    return -1;
  }

  return 0;
} //simple
The output is:
Code:
in simp
fv = 200.000000
pv = 0.000000
r = 4.500000
t = 2.000000
None of the if's are taken.

Can someone explain why, or what I'm doing wrong here?
Thanks.
 
Old 01-10-2008, 03:55 PM   #2
bigearsbilly
Senior Member
 
Registered: Mar 2004
Location: england
Distribution: Mint, Armbian, NetBSD, Puppy, Raspbian
Posts: 3,515

Rep: Reputation: 239Reputation: 239Reputation: 239
hmmm, it works on solaris 10
(I use the Sun compiler)


Code:
#include <stdio.h>


int simple(double fv, double pv, double r, double t) {
  printf("in simp\n");
  printf("fv = %lf\n", fv);
  printf("pv = %lf\n", pv);
  printf("r = %lf\n", r);
  printf("t = %lf\n", t);

  if(0.0 == fv) {
    printf("Finding FV\n");
  } else if(0.0 == pv) {
    printf("Finding PV\n");
  } else if(0.0 == r) {
    printf("Finding R\n");
  } else if(0.0 == t) {
    printf("Finding T\n");
  } else {
    return -1;
  }

  return 0;
} //simple

int main(void)
{
    simple(200,0.000000,4.5,2);
}
Code:
$ 
$ ./1
in simp
fv = 200.000000
pv = 0.000000
r = 4.500000
t = 2.000000
Finding PV
$
 
Old 01-10-2008, 03:59 PM   #3
h/w
Senior Member
 
Registered: Mar 2003
Location: New York, NY
Distribution: Debian Testing
Posts: 1,286

Original Poster
Rep: Reputation: 46
I should have mentioned I was trying this on a cygwin env. Never saw this before when I worked on any of the *nix env's myself.
Strange, but there must be a reason ...
 
Old 01-10-2008, 04:01 PM   #4
bigearsbilly
Senior Member
 
Registered: Mar 2004
Location: england
Distribution: Mint, Armbian, NetBSD, Puppy, Raspbian
Posts: 3,515

Rep: Reputation: 239Reputation: 239Reputation: 239
unfort I can't test it as I don't have any DOS op systems.


I could fire up my laptop and start xp on my vmware I suppose.
 
Old 01-10-2008, 04:31 PM   #5
paulsm4
LQ Guru
 
Registered: Mar 2004
Distribution: SusE 8.2
Posts: 5,863
Blog Entries: 1

Rep: Reputation: Disabled
h/w, bigearsbilly -

For grins, I cut/pasted the original subroutine and bigearsbilly's "main()" ... and got exactly the same results as bigearsbilly.

Everything looks OK.

On both DJGPP (GCC 4.2, DOS) and SuSE (GCC 3.3.5, Linux):
Quote:
in simp
fv = 200.000000
pv = 0.000000
r = 4.500000
t = 2.000000
Finding PV
'Sounds like a problem with your version of Cygwin C/C++?
 
Old 01-10-2008, 06:51 PM   #6
makyo
Member
 
Registered: Aug 2006
Location: Saint Paul, MN, USA
Distribution: {Free,Open}BSD, CentOS, Debian, Fedora, Solaris, SuSE
Posts: 735

Rep: Reputation: 76
Hi.

A display of "0.000000" does not mean the item is zero. It means that to 7 places the value is zero.

Although this may not be the cause of the situation here, floating point comparisons should almost never be for equality because of round-off that occurs in calculation with the approximations we use.

Perhaps printing the values in hex or octal would be useful.

Also we don't know (I don't know) what instructions are generated for the comparison in the if ... cheers, makyo
 
Old 01-10-2008, 07:44 PM   #7
paulsm4
LQ Guru
 
Registered: Mar 2004
Distribution: SusE 8.2
Posts: 5,863
Blog Entries: 1

Rep: Reputation: Disabled
Hi, Makyo -

Although in general your argument is correct...
... but an IEEE 754 "0.0" is binary identical to "0.000000000000000":
http://en.wikipedia.org/wiki/IEEE_754

Quote:
Quote:
Although this may not be the cause of the situation here, floating point comparisons should almost never be for equality because of round-off that occurs in calculation with the approximations
<= I agree completely
Quote:
Quote:
Perhaps printing the values in hex or octal would be useful.
<= An excellent suggestion. I'm curious myself!
H/W -
Could you please:
1. Tell us your Cygin/GCC version ("gcc -v" should tell you)
2. Tell us what kind of PC you're running on (who knows - maybe you're using some kind of FPU that doesn't use IEEE floating point!)
3. Dump the data values in hex (if convenient: gdb is one way)
4. Post back the results (we're curious!)

Thanx in advance .. PSM
 
Old 01-10-2008, 08:22 PM   #8
makyo
Member
 
Registered: Aug 2006
Location: Saint Paul, MN, USA
Distribution: {Free,Open}BSD, CentOS, Debian, Fedora, Solaris, SuSE
Posts: 735

Rep: Reputation: 76
Hi, paulsm4.
Quote:
Originally Posted by paulsm4 View Post
Although in general your argument is correct...
... but an IEEE 754 "0.0" is binary identical to "0.000000000000000":
http://en.wikipedia.org/wiki/IEEE_754
That was not the thrust of my comment, I should have been more precise. I was writing about the result of the printf statement.

Most of the tests that people performed were with calls that specified constants. The OP did not share how the argument values were obtained when the call was made ... cheers, makyo
 
Old 01-11-2008, 06:14 AM   #9
bigearsbilly
Senior Member
 
Registered: Mar 2004
Location: england
Distribution: Mint, Armbian, NetBSD, Puppy, Raspbian
Posts: 3,515

Rep: Reputation: 239Reputation: 239Reputation: 239
Quote:
Originally Posted by makyo View Post
Hi.

Although this may not be the cause of the situation here, floating point comparisons should almost never be for equality because of round-off that occurs in calculation with the approximations we use.
exactly, observe:

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


int main(void)
{
        float  y;
        float  x;

        for(;;) {
            printf("\nEnter a number:");
            scanf("%f", &x);
            y = sqrtf(x);
            printf("x=%f, y=%.33f\n", x, y);
            y *= y;
            printf("x=%f, y=%.33f\n", x, y);
        }
}
Code:
Enter a number:99

x=99.000000, y=9.949873924255371093750000000000000
x=99.000000, y=98.999992370605468750000000000000000
 
Old 01-11-2008, 09:20 AM   #10
h/w
Senior Member
 
Registered: Mar 2003
Location: New York, NY
Distribution: Debian Testing
Posts: 1,286

Original Poster
Rep: Reputation: 46
Thanks for the replies, all.
I'm aware of not doing FP compares, but had assumed that zero would not have this same behaviour. I still am not convinced entirely as we don't see this on other systems, but hey ...

paulsm4: it's gcc 3.4.4 on a 64-bit Windows XP. Would using a %o format specifier do to get the octal? Wouldn't it be incorrect against "double's"?

Thanks again.
 
Old 01-11-2008, 11:12 AM   #11
paulsm4
LQ Guru
 
Registered: Mar 2004
Distribution: SusE 8.2
Posts: 5,863
Blog Entries: 1

Rep: Reputation: Disabled
Hi -

I think we're all on the same page:

a) checking for equality with floating point numbers (which are, by definition, imprecise) is dangerous...
... but ..
b) you *should* be able to compare a double variable with the value "0.0" with a floating point literal "0.0" and reliably get "equals".

For whatever it's worth, I tried your program on a *third* different PC: a 64-bit AMD running Suse 10.x/Gnu 4.x... and it worked OK. No problems with "0.0".

I guess I'd be suspicious of your copy of Cygwin. If you wanted to pursue it further, the next step would be to compile with "gcc -S" and look at the assembler output of the comparision.

Your .. PSM
 
Old 01-11-2008, 12:19 PM   #12
h/w
Senior Member
 
Registered: Mar 2003
Location: New York, NY
Distribution: Debian Testing
Posts: 1,286

Original Poster
Rep: Reputation: 46
Hi Paul,
It's not worth the effort to look into what makes it different on cygwin. It was just a short program I was writing, and it just so happens it was on an env I don't use otherwise (cygwin.)
Anyway, the topic and all your replies just iterated some good points to remember.
Thanks all.
 
Old 01-11-2008, 12:38 PM   #13
jim mcnamara
Member
 
Registered: May 2002
Posts: 964

Rep: Reputation: 36
The C standard defines macros like isgreaterequal, isgreater, and so on for comparing fp datatypes. Therefore,
Code:
if ( ! islessgreater(a,b))
is one sure way to do a == boolean compare for floating point values. The advantage of the macros aside from portability, is that it will not raise exceptions on non-normal fp numbers.

See math.h for all of them.
 
Old 01-11-2008, 12:51 PM   #14
h/w
Senior Member
 
Registered: Mar 2003
Location: New York, NY
Distribution: Debian Testing
Posts: 1,286

Original Poster
Rep: Reputation: 46
Quote:
Originally Posted by jim mcnamara View Post
The C standard defines macros like isgreaterequal, isgreater, and so on for comparing fp datatypes. Therefore,
Code:
if ( ! islessgreater(a,b))
is one sure way to do a == boolean compare for floating point values. The advantage of the macros aside from portability, is that it will not raise exceptions on non-normal fp numbers.

See math.h for all of them.
Interesting, jim. Wasn't aware of those macros.
Thanks.

Last edited by h/w; 01-11-2008 at 12:54 PM.
 
Old 01-11-2008, 01:52 PM   #15
paulsm4
LQ Guru
 
Registered: Mar 2004
Distribution: SusE 8.2
Posts: 5,863
Blog Entries: 1

Rep: Reputation: Disabled
Hi, Jim -

"islessgreater()" and friends are ISO C99 macros. Newer versions of GCC/Linux are pretty good about supporting them, but you're not going to find them elsewhere (for example, it's *not* in my copy of MSVC ... but I haven't seen the new "Orcas"/VS2008 yet ;-))

Even then, you probably have to add special flags to get it to compile/link, e.g.:
Quote:
gcc -std=c99 -o simple simple.c -lm
Again, the basic issue is that what H/W was trying *should* work. I would definitely characterize the problem as a compiler issue, *not* a programming error.

IMHO .. PSM
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
how to compare munna_dude Programming 10 03-21-2007 07:50 AM
Double the desktop, not double the fun! bizshop SUSE / openSUSE 3 08-26-2005 12:22 PM
compare two folders bluenectar Linux - Newbie 10 08-04-2005 11:23 PM
How do I compare 2 files? linuxhippy Slackware 6 03-26-2005 01:54 AM
compare string in C++ danxl Programming 3 11-02-2003 02:14 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 01:13 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration