473,326 Members | 2,732 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,326 software developers and data experts.

Comparing double in for loop

Hi all,

i have encountered the strangest behavior. Check out this simple
program:

#include <stdio.h>

int main()
{
double time = 1;
double i = 0;

for (double i = 0; i < time ; i+=0.01 )
{
if ( i == 0.15 )
{
printf( "found %f\n", i);
}
if ( i < 0.1 )
{
printf( "foundXX %f\n", i);
}
}

return 1;
}

What would you expect to be printed:
All the numbers from 0.0 to 0.9 with the prefex: foundXX
and last line in output should be found 0.15 - right?!
Wrong... what I get is all the numbers from 0.0 to 0.1 printed
(including 0.1!!)
When checking if ( i==0.1) { printf( "foundXX %f\n",i);} it does not
print foundXX 0.1!!
Why exactly does it think that 0.1 is < than 0.1!!??

anyone?

Thanks
Apr 9 '08 #1
18 2854
em************@gmail.com writes:
>Hi all,
>i have encountered the strangest behavior.
See
http://www.eason.com/library/math/floatingmath.pdf
or (easier and more appropriate for your problem)
http://www.mathworks.com/company/new...all96Cleve.pdf
Apr 9 '08 #2
Tim Love wrote:
http://www.eason.com/library/math/floatingmath.pdf
or (easier and more appropriate for your problem)
http://www.mathworks.com/company/new...all96Cleve.pdf
Good reading material. For a quick answer:

http://www.parashift.com/c++-faq-lit...html#faq-29.17
Apr 9 '08 #3
em************@gmail.com wrote:
for (double i = 0; i < time ; i+=0.01 )
{
if ( i == 0.15 )
{
printf( "found %f\n", i);
}
if ( i < 0.1 )
{
printf( "foundXX %f\n", i);
}
}
As others have pointed out, 0.01 cannot be represented accurately with
floating point numbers (for the same reason as eg. 1/3 cannot be
represented accurately with decimal numbers).

Clearly you want a precise number of iterations to your loop, and you
want precise control on what happens with some precise values of the
loop counter. In those cases what you should do is to use an integer
loop counter, and calculate the floating point value from it. In other
words:

for(int i = 0; i < 100; ++i)
{
double value = i/100.0;

if(i == 15) std::cout << "found " << value << "\n";
if(i < 10) std::cout << "foundXX " << value << "\n";
}

The integer loop counter will make sure that an accurate number of
iterations is performed, and comparing this integer loop counter in the
conditionals will make sure that those conditionals give an accurate
result. Whenever the floating-point value needs to be used, use the
'value' variable, as exemplified above.
Apr 9 '08 #4
Mi***************@gmail.com wrote:
Machine double numbers are a finite subset of the
infinite real number domain. The operations on them executed by a
computer are similar but not identical to the math +, -, *, /, ...
operators 0.1 + 0.1 + 0.1 + 0.1 + 0.1 .

Then why doesn't an implementation use a large number of bits, for
people that want accuracy and also for x==y to work?
Like 8,000 bits or 8,000,000 bits or any number of bits necessary to
store all the possible numbers for double for example.
Apr 9 '08 #5
"Ioannis Vranos" <iv*****@nospam.no.spamfreemail.grwrote in message
news:ft***********@ulysses.noc.ntua.gr...
Mi***************@gmail.com wrote:
>Machine double numbers are a finite subset of the
infinite real number domain. The operations on them executed by a
computer are similar but not identical to the math +, -, *, /, ...
operators 0.1 + 0.1 + 0.1 + 0.1 + 0.1 .


Then why doesn't an implementation use a large number of bits, for
people that want accuracy and also for x==y to work?
Like 8,000 bits or 8,000,000 bits or any number of bits necessary to
store all the possible numbers for double for example.
Since 0.1 in binary is an infinate regression, it would take an infinite
number of bits to represent it.

--
Jim Langston
ta*******@rocketmail.com
Apr 10 '08 #6
Ioannis Vranos wrote:
Then why doesn't an implementation use a large number of bits, for
people that want accuracy and also for x==y to work?
Sure, if you want your program to be a thousand times slower.

The C++ compiler will usually use the FPU (and sometimes even SSE) to
make floating point calculations in hardware. To get larger floating
point values you would have to use a software library, which would be
enormously slower.

Besides, 0.1 is inaccurate in binary floating point format regardless
of the number of bits used (for the exact same reason as 1/3 is
inaccurate in decimal format regardless of how many decimals you use).
Like 8,000 bits or 8,000,000 bits or any number of bits necessary to
store all the possible numbers for double for example.
double already stores all possible numbers representable with a double.
Apr 10 '08 #7
On 10 Apr., 01:49, Ioannis Vranos <ivra...@nospam.no.spamfreemail.gr>
wrote:
Michael.Boehni...@gmail.com wrote:
Machine double numbers are a finite subset of the
infinite real number domain. The operations on them executed by a
computer are similar but not identical to the math +, -, *, /, ...
operators 0.1 + 0.1 + 0.1 + 0.1 + 0.1 .
oops. " != 0.5 " is missing.
>
Then why doesn't an implementation use a large number of bits, for
people that want accuracy and also for x==y to work?

Like 8,000 bits or 8,000,000 bits or any number of bits necessary to
store all the possible numbers for double for example.
A large number of bits is not enough, you'd need an *inifinte* number
of bits. Even if you extend the "normal" double numbers concept by
fractions (e.g. store two integer numbers 1 and 10 to represent 1/10),
you cannot represent the whole rational set (e.g. sqrt(2), pi or e
cannot be stored like this without loss of precision). Also, there is
an issue in performance: the more memory you use to store a single
value, the longer it will take to operate on them.

AFAIR, the current implementation by x86 CPUs uses 80 binary digits
for an extended precision floating point number internally and 64
binary digits to store a double in RAM memory. Should be enough for
most applications, *if* you follow the caveats mentioned before. -
Especially do not compare floats/doubles for (in)equality by != / ==
operators. If you want more precision you need to do it by application
code. This is considerably slower than using direct CPU/FPU commands
for floating point.

best,
Michael.
Apr 10 '08 #8
On Apr 10, 1:49 am, Ioannis Vranos <ivra...@nospam.no.spamfreemail.gr>
wrote:
Michael.Boehni...@gmail.com wrote:
Machine double numbers are a finite subset of the
infinite real number domain. The operations on them executed by a
computer are similar but not identical to the math +, -, *, /, ...
operators 0.1 + 0.1 + 0.1 + 0.1 + 0.1 .
Then why doesn't an implementation use a large number of bits, for
people that want accuracy and also for x==y to work?
Like 8,000 bits or 8,000,000 bits or any number of bits
necessary to store all the possible numbers for double for
example.
I'm not sure I understand. A double has enough bits to store
all possible numbers for double. By definition---if the number
can't be stored in a double, then it's not a possible number for
double.

The problem here is that the real number 0.1 is not a possible
number for double. And if you're asking that the implementation
use enough bits to store all possible real numbers, that's
lg2(N), where N is the number of possible real numbers. And off
hand, how many possible real numbers would you say there are?

In this particular case, an implementation could have masked the
problem by using a decimal representation for double. But that
will fail as soon as you try something like:

step = 1.0/3.0 ;
for ( value = 0.0 ; value != 1.0 ; value += step ) ...

(Back when I was working in this environment, I actually wrote a
proof that for all finite representations of floating point
values, the loop:

step = 1.0/N ;
for ( value = 0.0 ; value != 1.0 ; value += step )

will fail for some values of N.)

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Apr 10 '08 #9
Juha Nieminen wrote:
Ioannis Vranos wrote:
>Then why doesn't an implementation use a large number of bits, for
people that want accuracy and also for x==y to work?

Sure, if you want your program to be a thousand times slower.

The C++ compiler will usually use the FPU (and sometimes even SSE) to
make floating point calculations in hardware. To get larger floating
point values you would have to use a software library, which would be
enormously slower.

Besides, 0.1 is inaccurate in binary floating point format regardless
of the number of bits used (for the exact same reason as 1/3 is
inaccurate in decimal format regardless of how many decimals you use).

OK, but in math we have a symbol to represent the infinite repeating
sequences in decimals, like 7.33333... or 7.343434...
Apr 10 '08 #10
Ioannis Vranos wrote:
OK, but in math we have a symbol to represent the infinite repeating
sequences in decimals, like 7.33333... or 7.343434...
Floating point numbers are not the set of real numbers, nor are they
symbolic numbers. They are binary numbers with a fixed amount of bits.
You can't expect to be able to do with them what you can do in
"mathematics". You can only expect being able to approximate a finite
amount of operations.
Apr 10 '08 #11
A large number of bits is not enough, you'd need an *inifinte* number
of bits. Even if you extend the "normal" double numbers concept by
fractions (e.g. store two integer numbers 1 and 10 to represent 1/10),
you cannot represent the whole rational set (e.g. sqrt(2), pi or e
cannot be stored like this without loss of precision). Also, there is
an issue in performance: the more memory you use to store a single
value, the longer it will take to operate on them.
/pedant mode on

sqrt(2), pi and e are not in "the rational set" they are irrational,
meaning that they cannot be written as the quotient of two integers.
Moreover pi and e are transcendental meaning that they cannot be
expressed as the root of a polynomial equation (like sqrt(2) can since
it is one root of X^2 - 2 = 0). What you mean is the real set.

/pedant mode off

Apr 10 '08 #12
Juha Nieminen wrote:
Ioannis Vranos wrote:
>OK, but in math we have a symbol to represent the infinite repeating
sequences in decimals, like 7.33333... or 7.343434...

Floating point numbers are not the set of real numbers, nor are they
symbolic numbers. They are binary numbers with a fixed amount of bits.
You can't expect to be able to do with them what you can do in
"mathematics". You can only expect being able to approximate a finite
amount of operations.

Well I could think of an implementation where the (last) repeating
sequences could be identified with the use of extra bits. For example an
additional byte could be reserved and used for this in the style:

10000000 = The last decimal digit is repeating indefinetely,
example: 1.1111111111111111....

11000000 = The two last decimal digits are repeating indefinitely,
example: 1.1212121212121212....

11100000 = The three last decimal digits are repeating indefinitely,
example: 2.233234123123123123....

11110000 = The four last decimal digits are repeating indefinitely,
example, 1.543424321432143214321.....

etc.
Apr 10 '08 #13
Ioannis Vranos wrote:
Juha Nieminen wrote:
>Ioannis Vranos wrote:
>>OK, but in math we have a symbol to represent the infinite repeating
sequences in decimals, like 7.33333... or 7.343434...
Floating point numbers are not the set of real numbers, nor are they
symbolic numbers. They are binary numbers with a fixed amount of bits.
You can't expect to be able to do with them what you can do in
"mathematics". You can only expect being able to approximate a finite
amount of operations.


Well I could think of an implementation where the (last) repeating
sequences could be identified with the use of extra bits. For example an
additional byte could be reserved and used for this in the style:

10000000 = The last decimal digit is repeating indefinetely,
example: 1.1111111111111111....

11000000 = The two last decimal digits are repeating indefinitely,
example: 1.1212121212121212....

11100000 = The three last decimal digits are repeating indefinitely,
example: 2.233234123123123123....

11110000 = The four last decimal digits are repeating indefinitely,
example, 1.543424321432143214321.....

etc.

More accurately an example of storing the value of the second example
would be:

Stored in double bits:

1.12
Repeating flags (in our case one byte reserved for this):

11000000 = means .12 is repeated indefinitely
Apr 10 '08 #14
Ioannis Vranos wrote:
Juha Nieminen wrote:
Well I could think of an implementation where the (last) repeating
sequences could be identified with the use of extra bits. For example an
additional byte could be reserved and used for this in the style:
How about simply using integers, as I suggested in my other post?
Much easier and very efficient.
Apr 10 '08 #15
On 10 Apr., 15:48, brian tyler <brian.ty...@gmail.comwrote:
/pedant mode on
What you mean is the real set.
/pedant mode off
I was only testing if you all pay attention. Honest. No, really. Could
these eyes lie???

:-) You got me here.

Michael
Apr 10 '08 #16
On 10 Apr., 16:01, Ioannis Vranos <ivra...@nospam.no.spamfreemail.gr>
wrote:
Juha Nieminen wrote:
Well I could think of an implementation where the (last) repeating
sequences could be identified with the use of extra bits. For example an
additional byte could be reserved and used for this in the style:
By adding some extra bits, you certainly can extend the set of
representable real numbers. However, the length of the periodically
repeated portion also can have arbitrary length (up to the size of
the denominator if you convert to a normalized fraction). A number
like 1/x where x is roughly 10^9 may have a worst case period length
of 10^9... (of course, not all numbers in this range are *so* nasty).
You'd need to store this sequence somewhere at least once.

You'd be better off by just adding the extra bits to the mantissa.

best,

Michael
Apr 10 '08 #17
On Thu, 10 Apr 2008 07:40:06 -0700, Michael.Boehnisch wrote:
On 10 Apr., 15:48, brian tyler <brian.ty...@gmail.comwrote:
>/pedant mode on
What you mean is the real set.
/pedant mode off

I was only testing if you all pay attention. Honest. No, really. Could
these eyes lie???

:-) You got me here.

Michael
Haven't used the pedant mode tags in a while ;)

Brian
Apr 11 '08 #18
On Thu, 10 Apr 2008 07:40:06 -0700, Michael.Boehnisch wrote:
On 10 Apr., 15:48, brian tyler <brian.ty...@gmail.comwrote:
>/pedant mode on
What you mean is the real set.
/pedant mode off

I was only testing if you all pay attention. Honest. No, really. Could
these eyes lie???

:-) You got me here.

Michael
Haven't used the pedant mode tags in a while ;)

Brian
Jun 27 '08 #19

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

Similar topics

11
by: John | last post by:
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...
88
by: William Krick | last post by:
I'm currently evaluating two implementations of a case insensitive string comparison function to replace the non-ANSI stricmp(). Both of the implementations below seem to work fine but I'm...
7
by: Brian | last post by:
Hi, I have been trying to tune my vc7 compiled applications to perform at the same or (preferably) better speed of the same vc6 application. Both versions of my code are compiled with...
6
by: abbylee26 | last post by:
Im comparing values in a field while doing a loop if sAct<>myData(5,i) then At the end of the loop I make the value of sAct equal the current myData This will work when comparing other fields...
12
by: barcaroller | last post by:
Is it legal to compare the contents of two multi-field variables (of the same struct) using "==" and "!="? struct { int a; int b; } x,y; ...
1
by: blazted | last post by:
I am trying to find our how I would compare two matrix's. I have two matrix and I want to find out if they are equal, less or greater than. I created a double loop to loop through and compare...
27
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...
18
by: Carramba | last post by:
Hi! is there a better/faster way to compare mantissas of to real number then in following code? #include <stdio.h> #include <stdlib.h> int main(void) { float a,b; int test;
5
by: saneman | last post by:
I have a function: int F(double a) { if (a = =1.0) { return 22; } return 44; }
0
by: DolphinDB | last post by:
Tired of spending countless mintues downsampling your data? Look no further! In this article, you’ll learn how to efficiently downsample 6.48 billion high-frequency records to 61 million...
0
by: Vimpel783 | last post by:
Hello! Guys, I found this code on the Internet, but I need to modify it a little. It works well, the problem is this: Data is sent from only one cell, in this case B5, but it is necessary that data...
0
by: jfyes | last post by:
As a hardware engineer, after seeing that CEIWEI recently released a new tool for Modbus RTU Over TCP/UDP filtering and monitoring, I actively went to its official website to take a look. It turned...
0
by: ArrayDB | last post by:
The error message I've encountered is; ERROR:root:Error generating model response: exception: access violation writing 0x0000000000005140, which seems to be indicative of an access violation...
1
by: PapaRatzi | last post by:
Hello, I am teaching myself MS Access forms design and Visual Basic. I've created a table to capture a list of Top 30 singles and forms to capture new entries. The final step is a form (unbound)...
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
1
by: Shællîpôpï 09 | last post by:
If u are using a keypad phone, how do u turn on JavaScript, to access features like WhatsApp, Facebook, Instagram....
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...

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.