473,748 Members | 4,065 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Wrong results when comparing negative double variables in an if statement

Hi,

I encountered a strange problem while debugging C code for a
Windows-based application in LabWindows CVI V5.5, which led me to
write the test code below. I tried this code with a different compiler
and got the same erroneous result on two different PCs (with OS Win98
& Win98SE), so it appears to be a problem with ANSI C. I thought that
negative double variables could be compared as easily and *reliably*
as integers, but apparently not?

#include <ansi_c.h>

void main (void)
{
double a = -2.0, b = -2.0;

if (a > b)
printf("a is greater than b because a is %f and b is %f\n", a, b);
else
printf("a is not greater than b because a is %f and b is %f\n", a,
b);

a -= 0.01; // decrease value of a by 0.01
a += 0.01; // restore original value of a by increasing it by 0.01

if (a > b)
printf("a is greater than b because a is %f and b is %f\n", a, b);
else
printf("a is not greater than b because a is %f and b is %f\n", a,
b);
}

The output as copied from the emulated DOS window is:

a is not greater than b because a is -2.000000 and b is -2.000000
a is greater than b because a is -2.000000 and b is -2.000000

If I decrement and then increment a by 0.001, everything is fine, so
it doesn't look like there is a problem with the small magnitude of
the fractions.

I would be grateful for any solutions or suggestions to this problem
so that I can process *all* fractions correctly.

Thanks in advance,
John.
Nov 14 '05 #1
11 2390
John wrote:

Hi,

I encountered a strange problem while debugging C code for a
Windows-based application in LabWindows CVI V5.5, which led me to
write the test code below. I tried this code with a different compiler
and got the same erroneous result on two different PCs (with OS Win98
& Win98SE), so it appears to be a problem with ANSI C. I thought that
negative double variables could be compared as easily and *reliably*
as integers, but apparently not?


Apparently not, indeed. This is Question 14.1 in the
comp.lang.c Frequently Asked Questions (FAQ) list

http://www.eskimo.com/~scs/C-faq/top.html

.... and the next time somebody tells you that everybody's
"computer-literate" nowadays, you can cite the frequency
of this question as evidence to the contrary.

--
Er*********@sun .com
Nov 14 '05 #2
>I encountered a strange problem while debugging C code for a
Windows-based application in LabWindows CVI V5.5, which led me to
write the test code below. I tried this code with a different compiler
and got the same erroneous result on two different PCs (with OS Win98
& Win98SE), so it appears to be a problem with ANSI C. I thought that
negative double variables could be compared as easily and *reliably*
as integers, but apparently not?
Rounding error. If you're going to use floating-point numbers,
learn to live with it. And it's not only *NEGATIVE* numbers
that have the problem.
#include <ansi_c.h>
Non-standard include file.

void main (void)
main returns int, not void!
{
double a = -2.0, b = -2.0;

if (a > b)
printf("a is greater than b because a is %f and b is %f\n", a, b);
else
printf("a is not greater than b because a is %f and b is %f\n", a,
b);

a -= 0.01; // decrease value of a by 0.01
a += 0.01; // restore original value of a by increasing it by 0.01
No, you are NOT guaranteed that this will restore a to the original
value. There is no exact value of 0.01 in binary floating point.

if (a > b)
printf("a is greater than b because a is %f and b is %f\n", a, b);
else
printf("a is not greater than b because a is %f and b is %f\n", a,
b);
Print the numbers with unreasonably large precision, say %200.100f,
and you'll see what is going on. Also try printing 0.01 with
unreasonably large precision. Note that you're doing this for
debugging purposes, not because floating-point numbers have hundreds
of digits of accuracy, which they don't on any real machines I
have encountered, barring use of bignum packages which aren't
native C types.
}

The output as copied from the emulated DOS window is:

a is not greater than b because a is -2.000000 and b is -2.000000
a is greater than b because a is -2.000000 and b is -2.000000

If I decrement and then increment a by 0.001, everything is fine, so
it doesn't look like there is a problem with the small magnitude of
the fractions.
There is no exact value of 0.001 in binary floating point, either.
I would be grateful for any solutions or suggestions to this problem
so that I can process *all* fractions correctly.


Rounding error. Learn to live with it. (Very few decimal numbers
other than exact integers have exact representations in binary
floating point, a few exceptions being .5, .25, .75, .125, .375,
..625, and .875.) You might want to do this by explicitly rounding the
number yourself, and do NOT depend on what happens at the
exactly-half-way points.

Money is best represented as an integer quantity of the smallest
unit of currency you have to deal with (which might be cents in the
USA, or might be ten-thousandths of cents if you're an electric
company setting a price per kilowatt-hour to bill customers). You
can store this in an integer or floating type as appropriate for
the application. Bill Gates wouldn't want to use a 32-bit unsigned
long in cents (overflows at slightly under $43 million) for his net
worth, but it's fine for your average kid running a lemonade stand.
double or (for C99) long long might work well for all but the biggest
companies/governments.

Gordon L. Burditt
Nov 14 '05 #3
On Fri, 23 Apr 2004, John wrote:
Hi,

I encountered a strange problem while debugging C code for a
Windows-based application in LabWindows CVI V5.5, which led me to
write the test code below. I tried this code with a different compiler
and got the same erroneous result on two different PCs (with OS Win98
& Win98SE), so it appears to be a problem with ANSI C. I thought that
negative double variables could be compared as easily and *reliably*
as integers, but apparently not?
ANSI C is fine. Your assumption about comparing double variables is wrong.

Thing about this, there are infinite numbers between 0 and 1. Therefore
there is no way a computer can represent all numbers between 0 and 1 let
alone all real numbers in a larger range. This means that there will be
some numbers that are not represented. If I have:

double a = 2;
a += 0.01;
a -= 0.01;

Maybe 2.01 is a number that your compiler cannot represent. It might
decide to round up to the next closest number. When you decrement you
probably get a number that cannot be represented so it rounds up to the
next closet number. Now a will equal 2.0000000000000 1. This is called
representation error.

When you print them out, printf will only print 6 digits. So it looks like
a is still 2.000000 but it has just trimmed off the representation error
from the display. If you did something like:

printf("%020.20 f\n", a);

You'd see the real value of a. In <float.h> are macros to help with this
problem. Rather than comparing a to b you would look at the different
between a and b. If the different is smaller than EPSILON then you should
assume they are close enough to be called equal.
#include <ansi_c.h>

void main (void)
{
double a = -2.0, b = -2.0;

if (a > b)
printf("a is greater than b because a is %f and b is %f\n", a, b);
else
printf("a is not greater than b because a is %f and b is %f\n", a,
b);

a -= 0.01; // decrease value of a by 0.01
a += 0.01; // restore original value of a by increasing it by 0.01

if (a > b)
printf("a is greater than b because a is %f and b is %f\n", a, b);
else
printf("a is not greater than b because a is %f and b is %f\n", a,
b);
}

The output as copied from the emulated DOS window is:

a is not greater than b because a is -2.000000 and b is -2.000000
a is greater than b because a is -2.000000 and b is -2.000000

If I decrement and then increment a by 0.001, everything is fine, so
it doesn't look like there is a problem with the small magnitude of
the fractions.

I would be grateful for any solutions or suggestions to this problem
so that I can process *all* fractions correctly.

Thanks in advance,
John.


--
Send e-mail to: darrell at cs dot toronto dot edu
Don't send e-mail to vi************@ whitehouse.gov
Nov 14 '05 #4
John wrote:
Hi,

I encountered a strange problem while debugging C code for a
Windows-based application in LabWindows CVI V5.5, which led me to
write the test code below. I tried this code with a different compiler
and got the same erroneous result on two different PCs (with OS Win98
& Win98SE), so it appears to be a problem with ANSI C. I thought that
negative double variables could be compared as easily and *reliably*
as integers, but apparently not?

#include <ansi_c.h> The above is *NOT* an ANSI C header. It is non-standard.
void main (void)
It is invalid in a hosted implementation (which anything running under
Window is) for main to have *any* return type other than void.
{
double a = -2.0, b = -2.0;

if (a > b)
printf("a is greater than b because a is %f and b is %f\n", a, b);
else
printf("a is not greater than b because a is %f and b is %f\n", a,
b);


Please check the FAQ before posting. In particular, read the answers in
section 14 (floating point) <http://www.eskimo.com/~scs/C-faq/s14.html>.
If that does not suffice, remember that testing floating point numbers
for equality, which you are doing surreptitiously , is infested with
traps for the unwary.

Nov 14 '05 #5
[snips]

On Fri, 23 Apr 2004 19:58:34 -0400, Martin Ambuhl wrote:
void main (void)


It is invalid in a hosted implementation (which anything running under
Window is) for main to have *any* return type other than void.


Want to try that one again? Like, maybe, by suggesting a return type of,
say, int? :)
Nov 14 '05 #6
Hi,

Thank you all for your help. I'll represent all my numbers as integers
and only convert them to floating point numbers after processing.

Cheers,
John.
Nov 14 '05 #7
John wrote:

Hi,

Thank you all for your help. I'll represent all my numbers as integers
and only convert them to floating point numbers after processing.


You have just discovered that a screwdriver is not a
claw hammer, which is useful knowledge. You have decided
therefore to drive screws with your hammer, which is a sub-
optimal response ...

--
Er*********@sun .com
Nov 14 '05 #8

In article <c6************ @ID-227552.news.uni-berlin.de>, Martin Ambuhl <ma*****@earthl ink.net> writes:

It is invalid in a hosted implementation (which anything running under
Window is) ...


A great many Windows programs run in a freestanding implementation
known as "GUI mode". Such programs enter in a function named WinMain.

This freestanding implementation is itself implemented under a
hosted implementation, but a Windows GUI-mode program's main is
part of the implementation, not part of the user program.

Of course, if you're writing a Windows program, and it includes a
main, you're almost certainly writing to the hosted implementation
and that main should conform to the spec.

--
Michael Wojcik mi************@ microfocus.com

Dude, it helps to be smart if you're gonna be mean.
-- Darby Conley
Nov 14 '05 #9
Eric Sosman <Er*********@su n.com> wrote in message news:<40******* ********@sun.co m>...
John wrote:

Hi,

Thank you all for your help. I'll represent all my numbers as integers
and only convert them to floating point numbers after processing.


You have just discovered that a screwdriver is not a
claw hammer, which is useful knowledge. You have decided
therefore to drive screws with your hammer, which is a sub-
optimal response ...


That's a good analogy, but it's how the desktop calculators and
checkout cash registers do it. The decimal point is never typed in
although it appears on the receipt and the display in its fixed
position. I only need two decimal places so I think the hammer will
suffice. :)
Nov 14 '05 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

1
2113
by: dmiller23462 | last post by:
Hey guys.... I put an error-handling in my page and have it posted at the complete end of the code, see below(when people were putting in 's I was getting the delimiter errors). Great, I understand that now and it seems to be fixed but the data I'm pulling from the HTML fields is not being appended correctly do my Access DB....The field in the DB now reads " ' ". I understand why it does that (my function) but what I need it to read is...
4
1241
by: Spartaco | last post by:
This is a test I made that I believe has a wrong solution, they say the correct answer is C ?!? ---- You are an asp.net developer and currently you are working on te sql statement you will use to retrieve data from te customers table. Wat is te result of the following statement ? SELECT ID='identity', name='customer' FROM customers
318
13010
by: jacob navia | last post by:
Rcently I posted code in this group, to help a user that asked to know how he could find out the size of a block allocated with malloc. As always when I post something, the same group of people started to try to find possible errors, a harmless passtime they seem to enjoy. One of their remarks was that I used "int" instead of "size_t" for the input of my allocator function.
9
3062
by: Kelii | last post by:
I've been trying to get this piece to work for a few hours, but have given up. I hope someone out there can help, I think the issue is relatively straightforward, but being a novice, I'm stumped. Below you will find the code I've written and the error that results. I'm hoping that someone can give me some direction as to what syntax or parameter is missing from the code that is expected by VBA. Overview: I'm trying to copy calculated...
2
3389
by: Pugi! | last post by:
hi, I am using this code for checking wether a value (form input) is an integer and wether it is smaller than a given maximum and greater then a given minimum value: function checkInteger(&$value, $checks) { $err = ''; if (!is_numeric($value) || (floatval($value) != intval($value))) { $err .= 'Input must be an integer. ';
27
3863
by: Thomas Kowalski | last post by:
Hi everyone, To determine equality of two doubles a and b the following is often done: bool isEqual ( double a, double b ) { return ( fabs (a-b) < THRESHOLD ); } But this a approach usually fails if comparing doubles of different magnitude since it's hard or not possible to find a suitable threshold
31
1797
by: Jim Langston | last post by:
In Python 2.5 on intel, the statement 2**2**2**2**2 evaluates to 20035299304068464649790723515602557504478254755697514192650169737108940595563114 53089506130880933348101038234342907263181822949382118812668869506364761547029165 04187191635158796634721944293092798208430910485599057015931895963952486337236720 30029169695921561087649488892540908059114570376752085002066715637023661263597471...
32
2566
by: Joe | last post by:
I am just starting to use Object Oriented PHP coding, and I am seeing quite often the following (this example taken from a wiki): $wakka =& new Wakka($wakkaConfig); What exactly is the =&, and why is it different from = ?
7
2367
by: pcauchon | last post by:
When I try to run this code on my machine (iMac with MacOS 10.5), I get very strange results. I am using this compiler: i686-apple-darwin9-gcc-4.0.1 (GCC) 4.0.1 (Apple Inc. build 5465) The first program loop gives the results I expect (the value of 2**x when x is smaller than -1024 should be smaller than 10**-308). However the second loop gives values that seem to be corrupted somehow. Is it specific to iMac? Is there any way to detect...
0
8987
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
8826
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
9534
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
9366
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
0
9241
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
8239
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
0
4597
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
4867
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
3303
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.