
March 25th, 2006, 06:54 PM
#1
Comparing very small numbers problem
I am trying to compare two long doubles to check the difference between them is less than 1e14. However at about 1e9 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 1e14.
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)(i1)/40.0);
{
Approx2 = Approx1;
Nfact = fFactorial(N); //call factorial
Approx1 += (pow(X, N)/(Nfact)); //approximation of e^x
Difference = (Approx1  Approx2);
N++;
}while(Difference > 1E14);
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;
}
}
}

March 25th, 2006, 07:30 PM
#2
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

March 25th, 2006, 09:07 PM
#3
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 1E005 instead of 0.00001. In the form of 1.02E005 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;
}

March 25th, 2006, 11:40 PM
#4
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.

March 25th, 2006, 11:54 PM
#5
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 1E005 instead of 0.00001. In the form of 1.02E005 i can't compare it with my required string (the precision).
I don't understand what you're trying to do. On a highlevel, 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

March 26th, 2006, 12:09 AM
#6
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 10e14) 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.

March 26th, 2006, 12:11 AM
#7
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 10eprecision
test = 1;
return test;
}

March 26th, 2006, 04:07 AM
#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)(i1))/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 > 1E14);
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.48015873015872e05
2.75573192239868e06
2.75573192239868e07
2.50521083853834e08
2.08767569876388e09
1.60590438299732e10
1.14707455773494e11
7.6471641519138e13
4.7794667529244e14
2.81155307368941e15
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.
"inherit to be reused by code that uses the base class, not to reuse base class code", Sutter and Alexandrescu, C++ Coding Standards.
Club of lovers of the C++ typecasts cute syntax: Only recorded member.
Out of memory happens! Handle it properly!
Say no to g_new()!
Posting Permissions
 You may not post new threads
 You may not post replies
 You may not post attachments
 You may not edit your posts

Forum Rules

Click Here to Expand Forum to Full Width
OnDemand Webinars (sponsored)
