approximate equality
Sorry to clog the boards with my question but I've exhausted all other avenues of research. I have a program that recursively generates the powers of a number. Base x to the nth power. The numbers that this program generates are sometimes large and when comparing them to the oracle I am using even slight differences between them are causing my if statement to fail. Its there a method by which I can test two very large or small numbers to an approximated level of equality? I've though about parsing my outputs to a string loop with a charAT() method to go number by number but I think there might be a better way.
Also, I am student and this is my first time posting in the boards so if I have placed my post in the wrong place please feel free to /flame and I'll remove it immediately.
Thank you in advance to everyone for your assistance.
// tester
public class RecursivePowerTester {
public static void main(String[] args) {
int qq=0,correct=0,x=15,n=19;
double g;
double oracle;
System.out.println("This program will solve for X^n power");
while (qq<10000)
{
x = 1 + (int)(Math.random() * 20); // random number casted to int between 1-20
n = 1 + (int)(Math.random() * 10); // random number casted to int between 1-10
RecursivePower z = new RecursivePower(x,n);
g = z.getPow(x,n);
oracle = Math.pow(x,n);
if (g==oracle)
correct++;
else
System.out.println("My recursive method " + g + " Math.pow() oracle " + oracle + " x " + x + " n " + n + "howclose" + Math.abs(oracle - g));
qq++;
}
System.out.println("Out of " + qq + " operations the oracle and the recursive method had identical values " + correct + " times");
}
}
--
public class RecursivePower {
public RecursivePower(int xx, int nn) {
x=xx;
n=nn;
}
// self calling recursive method that multiplies the base to satisfy the nuber of powers
public double getPow(int x,int n)
{
if (n ==0)
return 1;
else return x * getPow(x,n-1);
}
private int x;
private int n;
}
[2191 byte] By [
MicMaca] at [2007-11-27 5:04:13]

You could cast the doubles back to int.
You could test the difference between your two values falls within some tolerance level.
c = Math.abs(a- b);
if(c <= tolerance) {
// values are essentials equal
}
P.S. why are you passing the values to your RecursivePower constructor and the getPow method?
My professor feels that even very simple code should be OO. :) Turning in an assignment with less than 2 classes is a certain zero :)
> P.S. why are you passing the values to your RecursivePower constructor and the getPow method?
> My professor feels that even very simple code should
> be OO. :) Turning in an assignment with less than 2
> classes is a certain zero :)
I think you don't understand flounder's remark. Your class contains 2 private members, which you initialise using your constructor. Afterwards you don't use them anymore since you defined parameters with the same names to your getPow() method. flounder's remark is to say: you don't need the member variables, however OO minded your professor is!
Yeah I totally missed the meaning of flounders response.
If I follow you I should have done the class like this instead?:
public class RecursivePower {
public RecursivePower(int xx, int nn) {
x=xx;
n=nn;
}
// self calling recursive method that multiplies the base to satisfy the nuber of powers
public double getPow()
{
if (n ==0)
return 1;
else return x * getPow(x,n-1);
}
private int x;
private int n;
}
You should keep the parameters in your getPow method, but you don't need member variables in your RecursivePower class.
> You should keep the parameters in your getPow method,
> but you don't need member variables in your RecursivePower class.
That's just a choice. If you choose this, then the getPow method can be static so you don't even have to instantiate RecursivePower:double power = RecursivePower.getPow(x, n);
If the prof likes OO, another choice can be to pass the parameters in the constructor and store them in member variables. Although this seems not handy to me:RecursivePower z = new RecursivePower(x, n);
double power = z.getPow();
By the way your problem will probably be solved if you follow flounder's first hint. That is casting the results to int before comparing.And for as long as the x and n parameters are int, getPow's return value should be int too. That will increase the precision.
Using flounders changes I am getting far fewer false negatives from my if statement and that is working out pretty well. I did add a second test to it aswell.
If ((g==oracle) || Math.abs(g-oracle) < Math.abs(oracle-(oracle*.999999999999998))) //not sure how many 9's I actually put in
// not infront of my code atm but its as many as I could use before I just
// ended up with a ton of zeros
correct++;
This has given me the "fuzzy" precision that I wanted but seems alittle too easy. Would you guys consider this "close enough".
> I wanted but seems alittle too
> easy. Would you guys consider this "close enough".
Computers can only represent so many digits of precision.
You can formalize your 999 value a bit by having it calculated (once) when the application starts up. You just put in a loop that compares previous and current value (modified) and stops when the values are the same.
Ive been looking into BigInteger typed variables. Would converting all my variables to that type remove the rounding errors that I am getting with the recursive method?
This is my code at the moment:
//tester class
public class RecursivePowerTester {
public static void main(String[] args) {
RecursivePower z = new RecursivePower();
int qq=0,correct=0,x=15,n=19;
double g;
double oracle;
System.out.println("This program will solve for X^n power");
while (qq<10000)
{
x = 1 + (int)(Math.random() * 90); // random number casted to int between 1-90
n = 1 + (int)(Math.random() * 90); // random number casted to int between 1-90
g = z.getPow(x,n);
oracle = Math.pow(x,n);
if ((g==oracle) ||(Math.abs(g-oracle) < Math.abs((oracle-(oracle*.999999999999998)) )))
correct++;
else {
System.out.println("My recursive method " + g + " Math.pow() oracle " + oracle + " x " + x + " n " + n + "howclose" + Math.abs(oracle - g));
}
qq++;
}
System.out.println("Out of " + qq + " operations the oracle and the recursive method had identical values " + correct + " times");
}
}
// recursive method class
//
public class RecursivePower {
public RecursivePower() {
}
// self calling recursive method that multiplies the base to satisfy the number of powers
public double getPow(int x,int n)
{
if (n ==0)
return 1;
else return x * getPow(x,n-1);
}
}
The .9999999..... variable in the if statement wasn't chosen randomly - its the largest I could get the program to handle before it just started spitting zeros out for that calculation.
> The .9999999..... variable in the if statement wasn't
> chosen randomly - its the largest I could get the
> program to handle before it just started spitting
> zeros out for that calculation.
Which is a standard way of doing a runtime calculation to determine precision.