3.03 - 3.03 != 0 ???

I wrote the following code:

using namespace std;

int main(){

  double X,ii;

  X=3.03;

  ii=X-3.03;
  ii=ii/0.03;
  ii=floor(ii);

  int i = int(ii);
  float t=(ii*0.03+3.03);
  t=X-t;
  t=t/0.03;

  cout<<endl<<"i = "<<i<<endl;
  cout<<endl<<"ii = "<<ii<<endl;
  cout<<endl<<"t = "<<t<<endl;

  return 0;

}

So I think the result should be zero if nothing went wrong, however, when i compile and excuted a.out, the following result occured:

i = 0

ii = 0

t = 9.53674e-07

Why is this the case?
eyuchenAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

RickJCommented:
Tell me..
If you change ii=X-3.03 to ii=X-X does it work ??
brettmjohnsonCommented:

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
cookreCommented:
Welcome to the world of floating point.

Given it's inherrent inability to represent many numbers EXACTLY (although reeal close, equality comparisons are seldom used.  The common way of doing such tests is to pick some small value epsilon that's considered close enough to zero then:

if (abs(x-y)<eps) equal=true;

I recall a mainframe based atmospheric model I converted many years ago from an IBM to UNIVAC.  The IBM was 32-bit - 8-bit characteristic and 24-bit mantissa normalized to the high-order nibble.  The Univac was 36-bit - 9-bit characteristic  and 27-bit mantissa normalized to the high-order bit.

When I was finished and showed the results to the researcher, he was livid - there was an order of magnitude difference between the two.  It took him a while to grasp the vagaries of floating point, accept that each result was valid, and recognize that his computational methods were woefully inadequate.
Bootstrap 4: Exploring New Features

Learn how to use and navigate the new features included in Bootstrap 4, the most popular HTML, CSS, and JavaScript framework for developing responsive, mobile-first websites.

eyuchenAuthor Commented:
I read the link brettmjohnson gave me.
According to it, I think the problem will be solved if I change
 
float t=(ii*0.03+3.03);
to:
double t=(ii*0.03+3.03);

so I did the following test:

#include<iostream>
#include<cmath>
using namespace std;

int main(){

  double X,ii;

  X=3.99;

  ii=X-3.03;
  ii=ii/0.03;
  ii=floor(ii);

  int i = int(ii);
  double t=(ii*0.03+3.03);
  t=X-t;
  t=t/0.03;

  cout<<endl<<"i = "<<i<<endl;
  cout<<endl<<"ii = "<<ii<<endl;
  cout<<endl<<"t = "<<t<<endl;

  return 0;

}

The result is:

i = 32

ii = 32

t = 1.4803e-14

Still not zero. (However, this time if I use X=3.03, t is indeed zero) Why??
brettmjohnsonCommented:
Please read the link more carefully.
Floating point values cannot be precisely represented using the limited precision of
the 32-bit or 64-bit encoding used by computers.   Arithmetic computation results in
minor rounding errors in the least significant bits.  Therefore, you cannot compare
floating point values for equality.  The best you can do is to determine that the values
are approximately equal - within a small margin of error.  Read the postings in the
linked question that mention "EPSILON".

eyuchenAuthor Commented:
Hi, I got the following message in the link you gave me.

"The problem is  your float variable is single precision, 32-buits probably, while all comparisons are done
using "double" precision.  So your single precision "a" is something like 0.699999, while the double precision "0.7" contant is maybe 0.699999998, a tiny bit different."

so, according to this, I believe, even if 0.7 is only 0.699999998 in double, double (x=0.7) - 0.7 should still be zero since they are round off in the same way.

?!
InteractiveMindCommented:
double a = 0.7 ;
double b = 0.7 ;

'a' will not necessarily be equal to 'b' ...
eyuchenAuthor Commented:
yeah, I think that's my question...may I ask why?

I agree float (a=0.7) != double (b=0.7)

but for double a and double b, if they are going to be round off,they should be round off in the same way...
cookreCommented:
When you read the line of code

double a=.7;

your decimal brain sees an exaxct figure.  The subsequent code, however, sees the floating point equivalent, which may or may not be an exact representation, cince it has only a finite number of negative powers of two to work with.  See:
http://en.wikipedia.org/wiki/IEEE_floating-point_standard

The decimal equivalent to floating point is scientific notation.  In that notation, for example, no finite number of digits can exactly represent 1/3 - you can only come close.  3.333333333333333333333333333 e-1 is pretty close, but not exact.
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Programming

From novice to tech pro — start learning today.