CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com

# Thread: Comparing very small numbers problem

1. Junior Member Join Date
Mar 2006
Posts
4

## Comparing very small numbers problem

I am trying to compare two long doubles to check the difference between them is less than 1e-14. However at about 1e-9 the code stops accepts the condition. I want to taylor expansion to keep iterating until the difference between the current value and the previous value is less than 1e-14.

The problem seems to be that long doubles in a comparison equate much earlier than they should. Does anyone know a get around?

I have tried searching the net but have no luck yet. Any help would be useful.

code in question
=====================================================

for (i=1; i<42; i++)
{
Approx1=1.0;
N=1;
Test=0;
X=((long double)(i-1)/40.0);
{
Approx2 = Approx1;
Nfact = fFactorial(N); //call factorial

Approx1 += (pow(X, N)/(Nfact)); //approximation of e^x

Difference = (Approx1 - Approx2);
N++;
}while(Difference > 1E-14);

cout << i << "\t" << X << "\t";
cout << Approx1 <<endl; //DEBUG

for (j=1; j<79; j++) //put the graph points in the right place
{
if (Test == 1)
ExpArray[i][j] = ' ';
else
{
if ((Approx1 - 1.0)> ((long double)j*2.0/80.0)) /
ExpArray[i][j] = ' ';
else
{
ExpArray[i][j] = '*';
Test = 1;
}
}

}  Reply With Quote

2. Elite Member Power Poster           Join Date
Apr 1999
Posts
27,449

## Re: Comparing very small numbers problem

One big mistake you're making:

You're supposed to be comparing the absolute value of the difference of the values, not just the difference of the values.

Regards,

Paul McKenzie  Reply With Quote

3. Junior Member Join Date
Mar 2006
Posts
4

## Re: Comparing very small numbers problem

Thanks but the abs isn't necessary as it always increments.

I've solved that problem, the fFactorial was an int not a long double, so after n=13 it turned negative.

Now I am trying to make something more robust.

I am using stringstream to convert the long double to a string. The problem i have is that the long double converts to 1E-005 instead of 0.00001. In the form of 1.02E-005 i can't compare it with my required string (the precision).

Any ideas?

int fString(long double Difference){ // string comparison

int test = 0, i;
string compare = "0.000000000000001", val;
stringstream s;
s << Difference; // insert double into stream
s >> val;
cout << compare << "\t" << val << "\n";
getchar();
for (i=0; compare[i] == val[i] ; i++)
cout << compare [i] << "\t" << val[i] << "\n";
if (i > 6)
test = 1;
return test;
}  Reply With Quote

4. Elite Member Power Poster           Join Date
Apr 1999
Posts
27,449

## Re: Comparing very small numbers problem Originally Posted by plainz
Thanks but the abs isn't necessary as it always increments.
What do you mean by "it always increments"? What is the "it"?

Bottom line: You are comparing if two values are within a certain tolerance level, and the correct way to do that is to take the absolute value of the difference. Look at any book or article on comparison of floating point values.

Regards,

Paul McKenzie
Last edited by Paul McKenzie; March 25th, 2006 at 11:45 PM.  Reply With Quote

5. Elite Member Power Poster           Join Date
Apr 1999
Posts
27,449

## Re: Comparing very small numbers problem Originally Posted by plainz
I am using stringstream to convert the long double to a string. The problem i have is that the long double converts to 1E-005 instead of 0.00001. In the form of 1.02E-005 i can't compare it with my required string (the precision).
I don't understand what you're trying to do. On a high-level, what is it that you are trying to accomplish?

Why not just make both doubles, and compare the difference of the doubles?

There is no guarantee that the double you give the strstream is what will be given back to you when you extract it from the strstream, just by the very nature of floating point values not being exact. So expecting exactly the same double to come out of the strstream as what you placed there is not realistic.

Regards,

Paul McKenzie  Reply With Quote

6. Junior Member Join Date
Mar 2006
Posts
4

## Re: Comparing very small numbers problem

Managed to solve the problems.

I know its best to use abs but what i meant was the value will always be positive so it is really redundant in my example.

I know with very small numbers (precision 10e-14) sometimes similar values are equated depending upon your computer and compiler. By converting the double to a string and comparing it with a string "0.00000000000000" i could check each if the characters match and return a true or false value depending if the precision had reached the required point. At least that's what i was informed was the most reliable way of comparing extreme numbers.

As i just check for precision i don't convert back to double.

What you say about stringstream does that mean it not a reliable way on converting long double to string?

Thanks for help anyways.  Reply With Quote

7. Junior Member Join Date
Mar 2006
Posts
4

## Re: Comparing very small numbers problem

This is what i ended up with for the precision test:

int fString(long double Difference, short int precision){ // string comparison to get accurate check of difference
int test = 0, i=0;
string compare = "0.000000000000000000", val; //will not be more than this
stringstream s;
s << fixed; //fixed otherwise uses scientific notation
s.precision(15); //overdo precision
s << Difference; // insert double into stream
s >> val;
// cout << endl << Difference <<endl; // debugcode
for (i=0; compare[i] == val[i] ; i++);
if (i > (precision)) // so precision is greater than 10e-precision
test = 1;
return test;
}  Reply With Quote

8. ## Re: Comparing very small numbers problem

I tried that code:
Code:
```#include <cmath>
#include <iostream>
using std::cout;
using std::endl;

long double fFactorial(int N)
{
long double r=1;
while(N>0) {r *= N;--N;}
return r;
}

int main()
{
int i;
long double Approx1,Approx2,Nfact,Difference;
long double X;
int N;

cout.precision(15);
for (i=1; i<42; i++)
{
Approx1=1.0;
N=1;
X=(((long double)(i-1))/40.0);
do
{
Approx2 = Approx1;
Nfact = fFactorial(N); //call factorial

Approx1 += (std::pow(X,N)/(Nfact)); //approximation of e^x

Difference = (Approx1 - Approx2);
N++;
cout << Difference << '\n';
}while(Difference > 1E-14);

cout << i << "\t" << X << "\t";
cout << Approx1 <<endl; //DEBUG
}

}```
And, it works perfectly on my computer.

Here is the output of the last operations:
Code:
```1
0.5
0.166666666666667
0.0416666666666667
0.00833333333333333
0.00138888888888889
0.000198412698412698
2.48015873015872e-05
2.75573192239868e-06
2.75573192239868e-07
2.50521083853834e-08
2.08767569876388e-09
1.60590438299732e-10
1.14707455773494e-11
7.6471641519138e-13
4.7794667529244e-14
2.81155307368941e-15
41      1       2.71828182845905``` Originally Posted by plainz
By converting the double to a string and comparing it with a string "0.00000000000000" i could check each if the characters match and return a true or false value depending if the precision had reached the required point.
You can only loose precision like that.  Reply With Quote

#### Posting Permissions

• You may not post new threads
• You may not post replies
• You may not post attachments
• You may not edit your posts
• 