Search code examples
javapow

Simple code doesn't output all required results


I have Java code that does the following:

1. Works with all combinations of integers a,b from 2 to 100 in sets of two. For instance, 2,2, 2,3,...,100,100. I just use two for loops for that.

2. For each set, checks whether the gcd of both integers is 1 (ignores sets where the gcd is 2 or more). I use the BigInteger Class because it has a method for that.

3. If the gcd is 1, check whether each of the two integers can be reconciled into a perfect power of base2 or more and exponent 3 or more. This is how I do that: For instance, let's consider the set 8,27. First, the code finds the max of the two. Then, for this set, the maximum power we can check for is Math.log10(27)/Math.log10(2) because the least the base can be is 2. This is just a trick from the field of mathematics. Hold that in variable powlim. I then use a for loop and Math.pow to check if all of the two integers have perfect nth roots like so;

for (double power = 3; power <= powlim; power++) {
      double roota = Math.pow(a, 1.0 / power);
      double rootb = Math.pow(b, 1.0 / power);

if ((Math.pow(Math.round(roota), power) == a) == true &&
   (Math.pow(Math.round(rootb), power) == b) == true) {

if (a < b) {
        System.out.println(a + "\t" + b);
           }
}
  1. The a<b condition makes sure that I don't get duplicate values such as both 8,27 and 27,8. For my purposes, the two are one and the same thing. Below is the entire code:
public static void main(String[] args) {
    for (int a = 2; a <= 100; a++) {
        for (int b = 2; b <= 100; b++) {
            BigInteger newa = BigInteger.valueOf(a);
            BigInteger newb = BigInteger.valueOf(b);
            BigInteger thegcd = newa.gcd(newb);
            if (thegcd.compareTo(BigInteger.ONE) == 0) {
                double highest = Math.max(a, b);
                double powlim = (Math.log10(highest) / Math.log10(2.0));

                for (double power = 3; power <= powlim; power++) {
                    double roota = Math.pow(a, 1.0 / power);
                    double rootb = Math.pow(b, 1.0 / power);

                    if ((Math.pow(Math.round(roota), power) == a) == true
                            && (Math.pow(Math.round(rootb), power) == b) == true {

                        if (a < b) {
                            System.out.println(a + "\t" + b);
                        }
                    }
                }
            }
        }
    }
}

So far so good. The code works fine. However, some few outputs that meet all the above criteria are ignored. For instance, when I run the above code I get;
8,27
16,81
27,64
What I don't understand is why a set like 8,81 is ignored. Its gcd is 1 and both of those integers can be expressed as perfect powers of base 2 or more and exponent 3 or more. 8 is 2^3 and 27 is 3^3. Why does this happen? Alternatively, it's fine if you provide your very own code that accomplishes the same task. I need to investigate how rare (or common) such sets are.


Solution

  • Math.pow(b, 1.0 / power); for 81 is 4.32 Then you round 4.32, and 4 at the power 3 is 64. 64 is not equal to 81. What you should be doing is: Math.round(Math.pow(roota, power)) == a

    Also, you need to iterate trough the powers of A and B separately, and check if the number can be rooted. This means an additional check if the rounded-down value of the double is the same as the double. (Meaning the pow 1/3, 1/4 yields an integer result.)

        public static void main(String[] args) {
            for (int a = 2; a <= 100; a++) {
                for (int b = 2; b <= 100; b++) {
                    BigInteger newa = BigInteger.valueOf(a);
                    BigInteger newb = BigInteger.valueOf(b);
                    BigInteger thegcd = newa.gcd(newb);
    
                    if (thegcd.compareTo(BigInteger.ONE) == 0) {
                        double highest = Math.max(a, b);
                        double powlim = (Math.log10(highest) / Math.log10(2.0));
    
                        for (double powerA = 3; powerA <= powlim; powerA++) {
                            double roota = Math.pow(a, 1.0 / powerA);
                            for (double powerB = 3; powerB <= powlim; powerB++) {
                                double rootb = Math.pow(b, 1.0 / powerB);
    
                                if (rootb == Math.floor(rootb) && roota == Math.floor(roota))  {
                                    if ((Math.round(Math.pow(roota, powerA)) == a) && (Math.round(Math.pow(rootb, powerB)) == b)) {
    
                                        if (a < b) {
                                            System.out.println(a + "\t" + b);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }