C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

simple problem??
Goto page 1, 2  Next
 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated)
View previous topic :: View next topic  
Author Message
baygross@gmail.com
Guest





PostPosted: Sun Nov 20, 2005 5:01 pm    Post subject: simple problem?? Reply with quote



#include <iostream>
using namespace std;

int main()
{
double num, num2;
for (num=-30; num<=30; num+=0.1)
{
num2=-2*(num*num)+3*(num);
if (num2==1)
cout << num << endl;
}
return(0);
}
***********************************************888
I know that when num=1 and also when num=0.5 then (num2==1) returns
true, but for some reason this code will never output: 1 and 0.5.

I am very new to c++, and would apreciate some suggestions?
-BG


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Thomas Maeder
Guest





PostPosted: Mon Nov 21, 2005 9:49 am    Post subject: Re: simple problem?? Reply with quote



[email]baygross (AT) gmail (DOT) com[/email] writes:

Quote:
#include <iostream

Side note: portably work the way you expect.


Quote:
using namespace std;

int main()
{
double num, num2;
for (num=-30; num<=30; num+=0.1)
{
num2=-2*(num*num)+3*(num);
if (num2==1)

The problem is with this comparison. Most floating point numbers can't
be represented accurately by computers because that would require an
infinite amount of memory. The floating point machinery of a computer
will therefore use approximate values for most floating point values.

Apparently, num2 will never reach exactly 1 (or, more accurately, the
value used by your computer to represent 1).

Using == and != on floating point values is therefore only a good idea
after careful study of the floating point machinery of the platform
the program runs on.

Often, it is good enough to consider two floating point values to be
equal if they belong to the same small interval.

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


Back to top
Alberto Ganesh Barbati
Guest





PostPosted: Mon Nov 21, 2005 10:02 am    Post subject: Re: simple problem?? Reply with quote



[email]baygross (AT) gmail (DOT) com[/email] wrote:
Quote:
#include using namespace std;

int main()
{
double num, num2;
for (num=-30; num<=30; num+=0.1)
{
num2=-2*(num*num)+3*(num);
if (num2==1)
cout << num << endl;
}
return(0);
}
***********************************************888
I know that when num=1 and also when num=0.5 then (num2==1) returns
true, but for some reason this code will never output: 1 and 0.5.

I am very new to c++, and would apreciate some suggestions?

When working with floating point numbers, you always need to take
representation errors and rounding errors into account. It might well be
that num is never exactly 1, but maybe something like 1.00000001 or
...99999999. In that case num2 won't be exactly 1 and the test will fail.
In fact, the == and != tests should always be used with extreme care and
are better avoided when working with floating point numbers.

A better test is the following:

int main()
{
const double epsilon = 0.0001;
double num, num2;
for (num=-30; num<=30; num+=0.1)
{
num2=-2*(num*num)+3*(num);
if (abs(num2 - 1) <= epsilon)
cout << num << endl;
}
return(0);
}

You can play with the value of epsilon to see what changes.

For your reference, integer operations, in absence of overflows, are
always exact. So if you multiply everything by ten the code will produce
the correct output:

int main()
{
int num, num2;
for (num=-300; num<=300; num+=1)
{
num2=-2*(num*num)+3*(num);
if (num2==10)
cout << num / 10.0 << endl;
}
return(0);
}

HTH,

Ganesh

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


Back to top
Thomas Richter
Guest





PostPosted: Mon Nov 21, 2005 10:30 am    Post subject: Re: simple problem?? Reply with quote

[email]baygross (AT) gmail (DOT) com[/email] wrote:

Quote:
int main()
{
double num, num2;
for (num=-30; num<=30; num+=0.1)

0.1 is not exactly representable as double on most platforms. Don't do
that, errors will accumulate.

Quote:
{
num2=-2*(num*num)+3*(num);
if (num2==1)

Don't compare floating point values for equality.

Quote:
cout << num << endl;
}
return(0);
}
***********************************************888
I know that when num=1 and also when num=0.5 then (num2==1) returns
true, but for some reason this code will never output: 1 and 0.5.

I am very new to c++, and would apreciate some suggestions?

Change the loop above to use an "int" as control variable, let the loop
run from -300 to 300, increment by one. Compute num from this variable.
Instead of comparing for equality, you could a) use an approximate
equality (check how much num2 differs from 1.0, and if close enough,
accept the output), or b) solve the quadradic expression directly.
There's no need to loop here in first place.

So long,
Thomas


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


Back to top
elazro
Guest





PostPosted: Mon Nov 21, 2005 10:31 am    Post subject: Re: simple problem?? Reply with quote

Your problem is that computers can't do exact floating point
arithmetic, since they have only finite precision. In particular, the
number 0.1 can not be represented exactly (it is probably stored as
approximately 0.10000000000000001). Thus, when you think num should be
1, it is actualy 1 plus a tiny fraction. Thus when num2 is calculated,
it is very close, but not quite, 1.0, and since it is not exactly
equal, the equality comparison fails.

This is a common problem when dealing with floating point computations
(in any language) - equality comparisons are next to useless (except
for a few special values such as 0, small integers, or dyadic
rationals). The solution is not to check for equality, but to check
that 2 numbers are close:

const double tolerance=1e-6;

....
if ( fabs(num2-1.0) they are equal

More sophisticated methods may be needed when dealing with very large
numbers (i.e. looking at the ratio between two numbers). If you need to
know more about floating point computations, google for "What every
computer scientist should know about floating-point" for a paper on the
subject.


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Carl Barron
Guest





PostPosted: Mon Nov 21, 2005 10:32 am    Post subject: Re: simple problem?? Reply with quote

In article <1132440553.516288.321890 (AT) o13g2000cwo (DOT) googlegroups.com>,
<baygross (AT) gmail (DOT) com> wrote:

Quote:
#include using namespace std;

int main()
{
double num, num2;
for (num=-30; num<=30; num+=0.1)
{
num2=-2*(num*num)+3*(num);
if (num2==1)
cout << num << endl;
}
return(0);
}
***********************************************888
I know that when num=1 and also when num=0.5 then (num2==1) returns
true, but for some reason this code will never output: 1 and 0.5.

I am very new to c++, and would apreciate some suggestions?
-BG


Precisely because num is never 1 or 0.5 due to round off errors in

0.1's representation in binary.

Don't compare floating point values directly with operator ==(), the
result requires an exact match and is not likely to occur as you noted
above.

simplest test is if(std::abs(num2-1.) < 1./16.)
f(x) = 3x - 2x^2 -1
f(0.4) = 1.2 - 1 - 2*.16 = -.12
f(0.6) = 0.8 - 2*,36 = .08
f(.9) = 1.7 - 2*,81 = .08
f(1.1) = 2.3 - 2*1.21 = 0.08
if(|f(x)| <1 /16 [=0.06125] ) is probably good enough for
this
if(std::num(num2-1) < 1./16,) is probably good enough replacement
for your if() line to obtain the result for this loop.

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


Back to top
usr.root@gmail.com
Guest





PostPosted: Mon Nov 21, 2005 10:34 am    Post subject: Re: simple problem?? Reply with quote


[email]baygross (AT) gmail (DOT) com[/email] 写�:

Quote:
#include using namespace std;

int main()
{
double num, num2;
for (num=-30; num<=30; num+=0.1)
{
num2=-2*(num*num)+3*(num);
if (num2==1)
cout << num << endl;
}
return(0);
}
***********************************************888
I know that when num=1 and also when num=0.5 then (num2==1) returns
true, but for some reason this code will never output: 1 and 0.5.

I am very new to c++, and would apreciate some suggestions?

Don't use "==" between double and int,becasue they will never have the
same value.
if you should do that ,you can use num2-1<0.xxxx


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


Back to top
Suki
Guest





PostPosted: Mon Nov 21, 2005 10:36 am    Post subject: Re: simple problem?? Reply with quote

The first thing you should keep in mind is never compare floating point
values for
equality. You can always compare them for < and > but not for ==.

To know why it is so, change the code to some thing like this.

Remove the if condition and re write the cout statement like this.

// It will print what you'd think 1 as something else. check it out.
cout << setprecision (17) << num << endl ;

or if you want to compare for equality then use this method.

#include if (fabs (num2 - 1) < DBL_EPSILON)
cout << num << endl ;

Or a more fancier way
#include if (fabs (num2 - 1) < numeric_limits cout << num < endl ;

Surya


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Victor Bazarov
Guest





PostPosted: Mon Nov 21, 2005 10:37 am    Post subject: Re: simple problem?? Reply with quote

[email]baygross (AT) gmail (DOT) com[/email] wrote:
Quote:
#include using namespace std;

int main()
{
double num, num2;
for (num=-30; num<=30; num+=0.1)
{
num2=-2*(num*num)+3*(num);
if (num2==1)
cout << num << endl;
}
return(0);
}
***********************************************888
I know that when num=1 and also when num=0.5 then (num2==1) returns
true, but for some reason this code will never output: 1 and 0.5.

I am very new to c++, and would apreciate some suggestions?

http://docs.sun.com/source/806-3568/ncg_goldberg.html

V



[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


Back to top
Ron House
Guest





PostPosted: Mon Nov 21, 2005 10:38 am    Post subject: Re: simple problem?? Reply with quote

[email]baygross (AT) gmail (DOT) com[/email] wrote:
Quote:
#include using namespace std;

int main()
{
double num, num2;
for (num=-30; num<=30; num+=0.1)
{
num2=-2*(num*num)+3*(num);
if (num2==1)
cout << num << endl;
}
return(0);
}
***********************************************888
I know that when num=1 and also when num=0.5 then (num2==1) returns
true, but for some reason this code will never output: 1 and 0.5.

I am very new to c++, and would apreciate some suggestions?

This is not a C++ problem but a problem in floating point arithmetic.
Float and double are floating point types that represent numbers as a
binary fraction multiplied by a power of two. That is, whereas normal
scientific notation is:

point decimal-fraction * 10^some-power

floating point notation is:

point binary-fraction * 2^some-power

Unfortunately, in binary fractions it is impossible to exactly represent
the value 0.1 (decimal tenth), just as in decimal fractions it is
impossible to exactly represent one third - you get an infinitely
repeating number.

So when you add "0.1", you are actually adding a value that differs ever
so slightly from 0.1, due to the finite number of digits of
representation in any actual computer. Therefore your code never tests
the exact values 1 and 0.5.

If you replace 0.1 with any number that can be represented exactly as a
binary fraction (and has 0.5 and 1 as multiples) then you will see what
you expect. For example, try replacing 1 with 0.0625 (which is 1/16th,
i.e. an inverse power of two).

--
Ron House [email]house (AT) usq (DOT) edu.au[/email]
http://www.sci.usq.edu.au/staff/house
Ethics website: http://www.sci.usq.edu.au/staff/house/goodness

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


Back to top
Neelesh Bodas
Guest





PostPosted: Mon Nov 21, 2005 12:40 pm    Post subject: Re: simple problem?? Reply with quote

[email]baygross (AT) gmail (DOT) com[/email] wrote:
Quote:
int main()
{
double num, num2;
for (num=-30; num<=30; num+=0.1)
{
num2=-2*(num*num)+3*(num);

num2 has been used without initialization.


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


Back to top
Francis Glassborow
Guest





PostPosted: Mon Nov 21, 2005 12:41 pm    Post subject: Re: simple problem?? Reply with quote

In article <1132440553.516288.321890 (AT) o13g2000cwo (DOT) googlegroups.com>,
[email]baygross (AT) gmail (DOT) com[/email] writes
Quote:
#include using namespace std;

int main()
{
double num, num2;
for (num=-30; num<=30; num+=0.1)
{
num2=-2*(num*num)+3*(num);
if (num2==1)
cout << num << endl;
}
return(0);
}
***********************************************888
I know that when num=1 and also when num=0.5 then (num2==1) returns
true, but for some reason this code will never output: 1 and 0.5.

I am very new to c++, and would apreciate some suggestions?

Yes, study up why comparisons of floating point values produce
surprising results in many if not all computing languages.



--
Francis Glassborow ACCU
Author of 'You Can Do It!' see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/youcandoit/projects


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


Back to top
kanze
Guest





PostPosted: Mon Nov 21, 2005 12:42 pm    Post subject: Re: simple problem?? Reply with quote

[email]baygross (AT) gmail (DOT) com[/email] wrote:
Quote:
#include using namespace std;

int main()
{
double num, num2;
for (num=-30; num<=30; num+=0.1)
{
num2=-2*(num*num)+3*(num);
if (num2==1)
cout << num << endl;
}
return(0);
}
***********************************************888

I know that when num=1 and also when num=0.5 then (num2==1)
returns true, but for some reason this code will never output:
1 and 0.5.

That's because num is never equal to 1.0, nor to 0.5.

Quote:
I am very new to c++, and would apreciate some suggestions?

Nothing to do with C++, really. You're being deceived by
appearances. You aren't incrementing num by 0.1 each time
threw the loop, because 0.1 isn't representable as a floating
point variable (at least on any reasonably modern machine). So
you're adding something very, very close, and the errors add up.

See http://cch.loria.fr/documentation/IEEE754/ACM/goldberg.pdf.

--
James Kanze GABI Software
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


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


Back to top
Selvin
Guest





PostPosted: Mon Nov 21, 2005 5:53 pm    Post subject: Re: simple problem?? Reply with quote

Witam,
Quote:
Or a more fancier way
#include <limits
if (fabs (num2 - 1) < numeric_limits cout << num < endl ;

i thought the same, but duno why its not working (MSVC++7.1)

#include #include <limits>
#include <ostream>
using namespace std;

int main()
{
double num, num2;
for (num=-30; num<=30; num+=0.1)
{
num2=-2*(num*num)+3*(num);
if (std::abs (num2 - 1.0) <
numeric_limits cout << num << endl;
}
return(0);
}

pozdrawiam

Przemek Sulikowski


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


Back to top
Selvin
Guest





PostPosted: Mon Nov 21, 2005 5:54 pm    Post subject: Re: simple problem?? Reply with quote

Maybe im wrong but....

Quote:
int main()
{

double num, num2;
for (num=-30; num<=30; num+=0.1)
....
num2 has been used without initialization.

in the same way num has been used without initialization, but it isnt
true...

Quote:
{
num2=-2*(num*num)+3*(num);

num2 has been used without initialization.

no, this is initialization, num2 is l-value in this statment

pozdrawiam

Przemek Sulikowski


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated) All times are GMT
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.