I have a very simple code and I don't understad it's result.
I think, this have to print "OK" but does not!

#include<iostream>
#include<math.h>

class real
{
  double value;
  double error;
public:
  real(double,double);
  friend bool operator==(const real&,const double);
};

real::real(double val, double err) : value(val), error(fabs(err)) {}

bool operator==(const real& x1, const double x2)
{
  // after substituting: 0.1 <= 0.1 is true!
  return fabs(x2-x1.value) <= x1.error;
}

int main()
{
  real x(1.1,0.1);
  if (x == 1.0) std::cout << "OK" << std::endl; 
  return 0;
}

Any idea?

x1.error is not 0.1 -- its 0.100000001.

bool operator==(const real& x1, const double x2)
{
  // after substituting: 0.1 <= 0.1 is true!
    bool b;
    double x = fabs(x2-x1.value);
    printf("x = %0.15f, x1.error = %0.25f\n", x, x1.error);
    if( x <= x1.error )
        b = true;
    else
        b = false;
    return b;
}

x = 0.100000000000000, x1.error = 0.1000000000000000100000000
FALSE

Press any key to continue . . .

Edited 6 Years Ago by Ancient Dragon: n/a

x1.error is not 0.1 -- its 0.100000001.

why???
its contructor is error=err (=0.1) and everything is double!!!???

Have you tried running your code through a debugger?

If you take the call to fabs out of your return statement in your operator== overload and store the result in a variable and then step through your code and take a look at the value, you'll see the problem.

Change your operator== overload to look like this:

bool operator==(const real& x1, const double x2)
{
	double x3  = fabs(x2 - x1.value);
	return x3 <= x1.error;
}

Step through the code and take a look at the values of x3 and x1.error.

Floating point mathematics strikes again!
This is down to the way that floating point values are handled in computer systems. In any computer system there are a finite number of numbers that can be accurately represented (depending on the architecture). Int values are quite straightforward and can be represented accurately, but floating point values are a bit trickier and are never exact, they are mere approximations. So not every possible decimal number can be accurately represented!

So although you've put 1.1 and 0.1 into your real class, these values are represented as something like 1.10000000000000001 and 0.100000000000000001.

fabs is giving you a result of 0.10000000000000009

Which isn't what you want when you're trying to compare one floating point number against another!

However, if you know how many decimal places you need to be accurate to (e.g. 4!), you could do something like this to compare the values:

bool operator==(const real& x1, const double x2)
{
	const int DECIMALSHIFT = 10000; // Shift 4 decimal places to the left

	// shift x1.error 4 decimal places to the left and store as an int:
	int z1 = (int)(x1.error * DECIMALSHIFT);
	// shift result of fabs by 4 decimal places and store as an int: 
	int z2 = (int)( (fabs(x2-x1.value)) * DECIMALSHIFT);

	// now compare the two values...
	return z2 < z1;
}

Which if you wanted, you could reduce down to this:

bool operator==(const real& x1, const double x2)
{
	const int DECIMALSHIFT = 10000;

	return (int)( (fabs(x2-x1.value)) * DECIMALSHIFT) <= (int)(x1.error * DECIMALSHIFT);
}

All we've done there is multiplied the floating point numbers by 10000 (shifting the numbers 4 decimal places to the left) and stored the results as ints (thus chopping off the unwanted additional decimal places).
If you want more or less decimal places, alter the number of zeros in DECIMALSHIFT!
Comparing the two resultant values then gives us our result (accurate to n decimal places, where n is the number of zeros in DECIMALSHIFT!)

Now the comparison in the return of your operator== function should work...Albeit accurate to n decimal places! :)

There are probably better solutions out there, but that was just off the top of my head!

Cheers for now,
Jas.

Thank you very much, but I don't understand something.
If I leave fabs away it works, so the problem is fabs,
however the absolute value function is a symmetric function mathematically,
and the double representation is also symmetric as I know
(which means tha the sign is stored separatelly in one bit)
so the fabs function has been written badly???

Edited 6 Years Ago by merse: n/a

This article has been dead for over six months. Start a new discussion instead.