Power of two integers

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;







up vote
4
down vote

favorite












Challenge:




Given a positive integer which fits in a $32$ bit signed integer,
find if it can be expressed as $A^P$ where $P > 1$ and $A > 0$.
A and P both should be integers.



Example



Input : 4

Output : True

as $2^2 = 4$.




My approach:



public class Solution 
public int isPower(int A)
int exp, base;

if( A == 1)
return 1;

if( A%2 == 0)

for( int i = 2; i < A; i+= 2 )

double variable = Math.log(A) / Math.log(i);
double formatted = Double.parseDouble(String.format( "%.6f", variable));

if((formatted== Math.floor(formatted)) && !Double.isInfinite(formatted))
return 1;

return 0;


else

for( int i = 3; i < A/2; i+= 2 )

double variable = Math.log(A) / Math.log(i);
double formatted = Double.parseDouble(String.format( "%.6f", variable));

if((formatted== Math.floor(formatted)) && !Double.isInfinite(formatted))
return 1;

return 0;






I have the following questions with regards to the above code:



  1. Is there any better method to solve this question?


  2. How can I further optimise the time and space complexity of the solution?







share|improve this question



























    up vote
    4
    down vote

    favorite












    Challenge:




    Given a positive integer which fits in a $32$ bit signed integer,
    find if it can be expressed as $A^P$ where $P > 1$ and $A > 0$.
    A and P both should be integers.



    Example



    Input : 4

    Output : True

    as $2^2 = 4$.




    My approach:



    public class Solution 
    public int isPower(int A)
    int exp, base;

    if( A == 1)
    return 1;

    if( A%2 == 0)

    for( int i = 2; i < A; i+= 2 )

    double variable = Math.log(A) / Math.log(i);
    double formatted = Double.parseDouble(String.format( "%.6f", variable));

    if((formatted== Math.floor(formatted)) && !Double.isInfinite(formatted))
    return 1;

    return 0;


    else

    for( int i = 3; i < A/2; i+= 2 )

    double variable = Math.log(A) / Math.log(i);
    double formatted = Double.parseDouble(String.format( "%.6f", variable));

    if((formatted== Math.floor(formatted)) && !Double.isInfinite(formatted))
    return 1;

    return 0;






    I have the following questions with regards to the above code:



    1. Is there any better method to solve this question?


    2. How can I further optimise the time and space complexity of the solution?







    share|improve this question























      up vote
      4
      down vote

      favorite









      up vote
      4
      down vote

      favorite











      Challenge:




      Given a positive integer which fits in a $32$ bit signed integer,
      find if it can be expressed as $A^P$ where $P > 1$ and $A > 0$.
      A and P both should be integers.



      Example



      Input : 4

      Output : True

      as $2^2 = 4$.




      My approach:



      public class Solution 
      public int isPower(int A)
      int exp, base;

      if( A == 1)
      return 1;

      if( A%2 == 0)

      for( int i = 2; i < A; i+= 2 )

      double variable = Math.log(A) / Math.log(i);
      double formatted = Double.parseDouble(String.format( "%.6f", variable));

      if((formatted== Math.floor(formatted)) && !Double.isInfinite(formatted))
      return 1;

      return 0;


      else

      for( int i = 3; i < A/2; i+= 2 )

      double variable = Math.log(A) / Math.log(i);
      double formatted = Double.parseDouble(String.format( "%.6f", variable));

      if((formatted== Math.floor(formatted)) && !Double.isInfinite(formatted))
      return 1;

      return 0;






      I have the following questions with regards to the above code:



      1. Is there any better method to solve this question?


      2. How can I further optimise the time and space complexity of the solution?







      share|improve this question













      Challenge:




      Given a positive integer which fits in a $32$ bit signed integer,
      find if it can be expressed as $A^P$ where $P > 1$ and $A > 0$.
      A and P both should be integers.



      Example



      Input : 4

      Output : True

      as $2^2 = 4$.




      My approach:



      public class Solution 
      public int isPower(int A)
      int exp, base;

      if( A == 1)
      return 1;

      if( A%2 == 0)

      for( int i = 2; i < A; i+= 2 )

      double variable = Math.log(A) / Math.log(i);
      double formatted = Double.parseDouble(String.format( "%.6f", variable));

      if((formatted== Math.floor(formatted)) && !Double.isInfinite(formatted))
      return 1;

      return 0;


      else

      for( int i = 3; i < A/2; i+= 2 )

      double variable = Math.log(A) / Math.log(i);
      double formatted = Double.parseDouble(String.format( "%.6f", variable));

      if((formatted== Math.floor(formatted)) && !Double.isInfinite(formatted))
      return 1;

      return 0;






      I have the following questions with regards to the above code:



      1. Is there any better method to solve this question?


      2. How can I further optimise the time and space complexity of the solution?









      share|improve this question












      share|improve this question




      share|improve this question








      edited Feb 27 at 11:29









      hjpotter92

      4,97611539




      4,97611539









      asked Feb 26 at 19:00









      Anirudh Thatipelli

      227211




      227211




















          4 Answers
          4






          active

          oldest

          votes

















          up vote
          5
          down vote













          Accuracy



          Floating-point approximations are not an acceptable substitute for integer arithmetic! Otherwise, you end up with mistakes, like Homer's bogus counterexample of Fermat's Last Theorem.



          Homer's false disproof of Fermat's Last Theorem



          How does that apply to your code? Consider isPower(2147483647). Your code yields 1, because it thinks that 463412 ≈ 2147483647. In fact, 463412 = 2147488281, and the correct answer is "false", since 2147483647 is prime.



          Filtering a number through a double → String → double round-trip conversion is especially egregious.



          Naming



          Try to choose variable names that are consistent with the nomenclature in the challenge. Your variable is really P; your i corresponds to A; your A should be named something else altogether — perhaps n.



          Suggested solution



          Count the number of times each prime factor of n occurs. You need to be able to segregate those factors into equal groups, with no lone factors left over.



          import java.util.PrimitiveIterator;
          import java.util.stream.IntStream;

          public class Solution
          /**
          * Calculates the GCD of two numbers using the Euclidean Algorithm.
          */
          private static int gcd(int a, int b)
          while (b != 0)
          int temp = b;
          b = a % b;
          a = temp;

          return a;


          public boolean isPower(int n)
          PrimitiveIterator.OfInt factors =
          IntStream.concat(IntStream.of(2), IntStream.iterate(3, i -> i + 2))
          .iterator();

          // Count the number of times each prime factor occurs
          IntStream.Builder exponents = IntStream.builder();
          int f, e;
          do
          f = factors.nextInt();
          for (e = 0; n % f == 0; e++)
          n /= f;

          if (e > 0)
          exponents.add(e);

          while (f < n);

          // Try to segregate the factors into equal groups with no loners.
          // If there is no GCD, then n was 1, so a=1, p=2 would work.
          int p = exponents.build().reduce(Solution::gcd).orElse(2);
          return p > 1;







          share|improve this answer























          • Thanks, I wasn't aware of this floating-point inconsistency while coding. My answer was being accepted as correct.
            – Anirudh Thatipelli
            Feb 27 at 6:06

















          up vote
          1
          down vote













          1. The challenge defines the output of your function to be true or false. Java has the boolean primitive to model exactly that. Your method should return a boolean not an int that "means" true when it's not 0 (as would be the case for C).


          2. It's generally accepted best practice in java to define each variable (and member) on its own line. exp and base should be declared on separate lines.


          3. It's easier on your brain to keep track of things, if you're using them directly after you introduced them. That is generally referred to as "Declaring variables as close as possible to their usage".


          4. The vast majority of java conventions states that binary and ternary operators should have spaces around the operators. In your code that applies to +=, % and sometimes ==. Generally your formatting seems to try matching some standard, but isn't quite consistent, as evidenced by / having spacing when you calculate variable, but not when inside a a for-loop's head...

            Above all you should strive to be consistent with formatting code. That makes it easier to read.


          5. Most Java conventions prefer opening braces to be on the same line as the block opening statement. That implies the same bracing style as you use for the method definition to extend to if, else and for statements.

            In addition to that I highly recommend placing braces wherever possible.


          6. Lastly: the for-loops in if (A % 2 == 0) and else only differ by their initial value. Aside from that they are the same. Why did you opt for using a step-size of two with starts differing by one when you could've just as well iterated with a step-size of 1?






          share|improve this answer






























            up vote
            0
            down vote













            For a given number N, you do a loop over the potential base numbers A, and calculate the exponent P, checking whether it's integer. This way, you have to loop over a lot of numbers.



            If you do it the other way round, with a loop over the potential exponents P, calculating the matching base A and checking that for an integer value, you only have to iterate from P=2 to P=30.



            I didn't check if your code works - I have my doubts, especially with the "check for integer" part.




            A few comments on your coding style:



            Your method isPower() is meant to check if the given number can be represented as a power A^P. Instead of an int you should return a boolean (true or false instead of 1 or 0).



            The naming of classes, methods, fields, variables and so on is crucial for the readability of code. They should reflect the thing they represent. So, isPower is a good name for a method that checks whether the number is a power. But names like variable don't help. Names like exp and base are good choices, but you only declare them and don't use them (any decent IDE will flag them as unused). One-letter names should be avoided as much as possible (with the exception of loop variables like i, j, or k).



            There are naming conventions in Java, especially variables should always begin with a lowercase letter. Long-term Java developers will automatically understand anything that begins with uppercase as a class name, and have a hard time if in your code, the conventions don't apply.



            Your indentation and placement of braces is unique. Following the usual style makes it easier to read your code and doesn't waste so much space (even the simple class presented here has lines too wide to fit into the space on this site).



            Code like



             if( A == 1)
            return 1;


            not surrounding the dependent statement with braces, is a maintenance risk. Imagine that later someone wants to add another statement here:



             if( A == 1)
            log.info("found a solution");
            return 1;


            That looks fine at a first glance, but effectively it's:



             if( A == 1) 
            log.info("found a solution");

            return 1;


            Not what you want, isn't it? So, I recommend to always use braces.



            Write Javadoc comments at least for all public classes and methods.



            After renaming, commenting and reformatting your code (but keeping your algorithm), we'd get:



            /**
            * Solution to the <a href=https://www.interviewbit.com/problems/power-of-two-integers/>
            * Power of Two Integers</a> problem.
            *
            * @author your name
            */
            public class Solution

            /**
            * Check if <code>power</code> can be represented as <code>A^P</code>
            * with A and P being integers, and P greater that 1.
            * @param power the number under test
            * @return true if <code>power</code> can be represented as <code>A^P</code>
            */
            public boolean isPower(int power)
            if (power == 1)
            return true;


            if (power % 2 == 0)
            for (int base = 2; base < power; base += 2)
            double exp = Math.log(power) / Math.log(base);
            double formattedExp = Double.parseDouble(String.format("%.6f", exp));

            if ((formattedExp == Math.floor(formattedExp)) && !Double.isInfinite(formattedExp))
            return true;


            return false;

            else
            for (int base = 3; base < power / 2; base += 2)
            double exp = Math.log(power) / Math.log(base);
            double formattedExp = Double.parseDouble(String.format("%.6f", exp));

            if ((formattedExp == Math.floor(formattedExp)) && !Double.isInfinite(formattedExp))
            return true;


            return false;








            share|improve this answer






























              up vote
              0
              down vote













              There are some valid points regarding coding style and floating point arithmetic, but I want to focus on improving the time complexity of the solution. From my experiments, it seems that simpler is better. Simply looping over bases and exponents yields a result which is >20x faster than the previous answers posted here.



              public class Solution 

              public static int pow2(int a, int b)
              int re = 1;
              while (b > 0)
              if ((b & 1) == 1)
              re *= a;

              b >>= 1;
              a *= a;

              return re;


              public boolean isPower(int n)
              if (n < 4)
              return n == 1;


              for (int a = 2; a < Math.sqrt(n)+1; a++)
              if (n % a*a == 0)
              for (int p = (int) (Math.log(n)/Math.log(a)); p < 32; p++)
              int result = pow2(a, p);
              if (result == n)
              return true;

              if (result > n)
              break;




              return false;




              Disclosure: I copied the pow2 function from here.



              Explanation: since the input was a positive integer, we first create special cases for n<4. For every other value of n, test every value of a which is a suitable candidate. There's no need to check beyond sqrt(n), because the lowest exponent is p=2.



              With some math, you can figure out that given the base a, the exponent p should be approximately log(n)/log(a). Since n fits within a signed 32-bit integer, we know that p<32.



              Then we simply compute a^p and check if it is equal to n. Simple as that. This code outputs identical results for all values of n less than 100000 (that's how far I tested) compared to previous solutions in this thread.



              Possible future improvements: remove all floating point arithmetic and instead use bit-shift operations to approximate the logarithm, and do a special case to see if n only has one bit set (e.g. 0b00100000), which implies that it is a power of 2.



              EDIT: additional speedup



              After some research, I concluded that reversing the search order would make the function faster. Since we know that 1<p<lg(n)+1, we can try all those values, and perform a binary search for the value of a.



              public boolean isPower(int n) 
              if (n < 4)
              return n == 1;


              int maxExponent = 0;
              int tempN = n;
              while (tempN > 0)
              maxExponent++;
              tempN >>= 1;

              int low_a;
              int high_a;
              int temp_a;
              int result;

              for (int p = 2; p < maxExponent+1; p++)

              low_a = 1;
              high_a = 1<<(maxExponent/p+1);

              while (high_a-low_a > 1)

              temp_a = (low_a+high_a)/2;
              result = pow2(temp_a, p);

              if (result == n)
              return true;

              if (result < n)
              low_a = temp_a;
              else
              high_a = temp_a;



              return false;



              Some included benchmarks:



              Time to calculate isPower for every number between 1 and 10^5:
              200_success' solution: 2.769842086 seconds
              My previous solution: 0.108119151 seconds
              My new solution: 0.034731273 seconds

              Time to calculate isPower for every number between 1 and 10^6:
              200_success' solution: ~30 seconds
              My previous solution: 2.833582944 seconds
              My new solution: 0.4383110970 seconds

              Time to calculate isPower for every number between 10^9 and 10^9+10^4:
              200_success' solution: not included
              My previous solution: 1.3411200 seconds
              My new solution: 0.014713117 seconds


              From this benchmark we can see that the new algorithm is much faster for large values of n, being almost 100 times faster in the last benchmark.






              share|improve this answer























                Your Answer




                StackExchange.ifUsing("editor", function ()
                return StackExchange.using("mathjaxEditing", function ()
                StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix)
                StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
                );
                );
                , "mathjax-editing");

                StackExchange.ifUsing("editor", function ()
                StackExchange.using("externalEditor", function ()
                StackExchange.using("snippets", function ()
                StackExchange.snippets.init();
                );
                );
                , "code-snippets");

                StackExchange.ready(function()
                var channelOptions =
                tags: "".split(" "),
                id: "196"
                ;
                initTagRenderer("".split(" "), "".split(" "), channelOptions);

                StackExchange.using("externalEditor", function()
                // Have to fire editor after snippets, if snippets enabled
                if (StackExchange.settings.snippets.snippetsEnabled)
                StackExchange.using("snippets", function()
                createEditor();
                );

                else
                createEditor();

                );

                function createEditor()
                StackExchange.prepareEditor(
                heartbeatType: 'answer',
                convertImagesToLinks: false,
                noModals: false,
                showLowRepImageUploadWarning: true,
                reputationToPostImages: null,
                bindNavPrevention: true,
                postfix: "",
                onDemand: true,
                discardSelector: ".discard-answer"
                ,immediatelyShowMarkdownHelp:true
                );



                );








                 

                draft saved


                draft discarded


















                StackExchange.ready(
                function ()
                StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f188392%2fpower-of-two-integers%23new-answer', 'question_page');

                );

                Post as a guest






























                4 Answers
                4






                active

                oldest

                votes








                4 Answers
                4






                active

                oldest

                votes









                active

                oldest

                votes






                active

                oldest

                votes








                up vote
                5
                down vote













                Accuracy



                Floating-point approximations are not an acceptable substitute for integer arithmetic! Otherwise, you end up with mistakes, like Homer's bogus counterexample of Fermat's Last Theorem.



                Homer's false disproof of Fermat's Last Theorem



                How does that apply to your code? Consider isPower(2147483647). Your code yields 1, because it thinks that 463412 ≈ 2147483647. In fact, 463412 = 2147488281, and the correct answer is "false", since 2147483647 is prime.



                Filtering a number through a double → String → double round-trip conversion is especially egregious.



                Naming



                Try to choose variable names that are consistent with the nomenclature in the challenge. Your variable is really P; your i corresponds to A; your A should be named something else altogether — perhaps n.



                Suggested solution



                Count the number of times each prime factor of n occurs. You need to be able to segregate those factors into equal groups, with no lone factors left over.



                import java.util.PrimitiveIterator;
                import java.util.stream.IntStream;

                public class Solution
                /**
                * Calculates the GCD of two numbers using the Euclidean Algorithm.
                */
                private static int gcd(int a, int b)
                while (b != 0)
                int temp = b;
                b = a % b;
                a = temp;

                return a;


                public boolean isPower(int n)
                PrimitiveIterator.OfInt factors =
                IntStream.concat(IntStream.of(2), IntStream.iterate(3, i -> i + 2))
                .iterator();

                // Count the number of times each prime factor occurs
                IntStream.Builder exponents = IntStream.builder();
                int f, e;
                do
                f = factors.nextInt();
                for (e = 0; n % f == 0; e++)
                n /= f;

                if (e > 0)
                exponents.add(e);

                while (f < n);

                // Try to segregate the factors into equal groups with no loners.
                // If there is no GCD, then n was 1, so a=1, p=2 would work.
                int p = exponents.build().reduce(Solution::gcd).orElse(2);
                return p > 1;







                share|improve this answer























                • Thanks, I wasn't aware of this floating-point inconsistency while coding. My answer was being accepted as correct.
                  – Anirudh Thatipelli
                  Feb 27 at 6:06














                up vote
                5
                down vote













                Accuracy



                Floating-point approximations are not an acceptable substitute for integer arithmetic! Otherwise, you end up with mistakes, like Homer's bogus counterexample of Fermat's Last Theorem.



                Homer's false disproof of Fermat's Last Theorem



                How does that apply to your code? Consider isPower(2147483647). Your code yields 1, because it thinks that 463412 ≈ 2147483647. In fact, 463412 = 2147488281, and the correct answer is "false", since 2147483647 is prime.



                Filtering a number through a double → String → double round-trip conversion is especially egregious.



                Naming



                Try to choose variable names that are consistent with the nomenclature in the challenge. Your variable is really P; your i corresponds to A; your A should be named something else altogether — perhaps n.



                Suggested solution



                Count the number of times each prime factor of n occurs. You need to be able to segregate those factors into equal groups, with no lone factors left over.



                import java.util.PrimitiveIterator;
                import java.util.stream.IntStream;

                public class Solution
                /**
                * Calculates the GCD of two numbers using the Euclidean Algorithm.
                */
                private static int gcd(int a, int b)
                while (b != 0)
                int temp = b;
                b = a % b;
                a = temp;

                return a;


                public boolean isPower(int n)
                PrimitiveIterator.OfInt factors =
                IntStream.concat(IntStream.of(2), IntStream.iterate(3, i -> i + 2))
                .iterator();

                // Count the number of times each prime factor occurs
                IntStream.Builder exponents = IntStream.builder();
                int f, e;
                do
                f = factors.nextInt();
                for (e = 0; n % f == 0; e++)
                n /= f;

                if (e > 0)
                exponents.add(e);

                while (f < n);

                // Try to segregate the factors into equal groups with no loners.
                // If there is no GCD, then n was 1, so a=1, p=2 would work.
                int p = exponents.build().reduce(Solution::gcd).orElse(2);
                return p > 1;







                share|improve this answer























                • Thanks, I wasn't aware of this floating-point inconsistency while coding. My answer was being accepted as correct.
                  – Anirudh Thatipelli
                  Feb 27 at 6:06












                up vote
                5
                down vote










                up vote
                5
                down vote









                Accuracy



                Floating-point approximations are not an acceptable substitute for integer arithmetic! Otherwise, you end up with mistakes, like Homer's bogus counterexample of Fermat's Last Theorem.



                Homer's false disproof of Fermat's Last Theorem



                How does that apply to your code? Consider isPower(2147483647). Your code yields 1, because it thinks that 463412 ≈ 2147483647. In fact, 463412 = 2147488281, and the correct answer is "false", since 2147483647 is prime.



                Filtering a number through a double → String → double round-trip conversion is especially egregious.



                Naming



                Try to choose variable names that are consistent with the nomenclature in the challenge. Your variable is really P; your i corresponds to A; your A should be named something else altogether — perhaps n.



                Suggested solution



                Count the number of times each prime factor of n occurs. You need to be able to segregate those factors into equal groups, with no lone factors left over.



                import java.util.PrimitiveIterator;
                import java.util.stream.IntStream;

                public class Solution
                /**
                * Calculates the GCD of two numbers using the Euclidean Algorithm.
                */
                private static int gcd(int a, int b)
                while (b != 0)
                int temp = b;
                b = a % b;
                a = temp;

                return a;


                public boolean isPower(int n)
                PrimitiveIterator.OfInt factors =
                IntStream.concat(IntStream.of(2), IntStream.iterate(3, i -> i + 2))
                .iterator();

                // Count the number of times each prime factor occurs
                IntStream.Builder exponents = IntStream.builder();
                int f, e;
                do
                f = factors.nextInt();
                for (e = 0; n % f == 0; e++)
                n /= f;

                if (e > 0)
                exponents.add(e);

                while (f < n);

                // Try to segregate the factors into equal groups with no loners.
                // If there is no GCD, then n was 1, so a=1, p=2 would work.
                int p = exponents.build().reduce(Solution::gcd).orElse(2);
                return p > 1;







                share|improve this answer















                Accuracy



                Floating-point approximations are not an acceptable substitute for integer arithmetic! Otherwise, you end up with mistakes, like Homer's bogus counterexample of Fermat's Last Theorem.



                Homer's false disproof of Fermat's Last Theorem



                How does that apply to your code? Consider isPower(2147483647). Your code yields 1, because it thinks that 463412 ≈ 2147483647. In fact, 463412 = 2147488281, and the correct answer is "false", since 2147483647 is prime.



                Filtering a number through a double → String → double round-trip conversion is especially egregious.



                Naming



                Try to choose variable names that are consistent with the nomenclature in the challenge. Your variable is really P; your i corresponds to A; your A should be named something else altogether — perhaps n.



                Suggested solution



                Count the number of times each prime factor of n occurs. You need to be able to segregate those factors into equal groups, with no lone factors left over.



                import java.util.PrimitiveIterator;
                import java.util.stream.IntStream;

                public class Solution
                /**
                * Calculates the GCD of two numbers using the Euclidean Algorithm.
                */
                private static int gcd(int a, int b)
                while (b != 0)
                int temp = b;
                b = a % b;
                a = temp;

                return a;


                public boolean isPower(int n)
                PrimitiveIterator.OfInt factors =
                IntStream.concat(IntStream.of(2), IntStream.iterate(3, i -> i + 2))
                .iterator();

                // Count the number of times each prime factor occurs
                IntStream.Builder exponents = IntStream.builder();
                int f, e;
                do
                f = factors.nextInt();
                for (e = 0; n % f == 0; e++)
                n /= f;

                if (e > 0)
                exponents.add(e);

                while (f < n);

                // Try to segregate the factors into equal groups with no loners.
                // If there is no GCD, then n was 1, so a=1, p=2 would work.
                int p = exponents.build().reduce(Solution::gcd).orElse(2);
                return p > 1;








                share|improve this answer















                share|improve this answer



                share|improve this answer








                edited Feb 27 at 8:07


























                answered Feb 27 at 3:49









                200_success

                123k14142399




                123k14142399











                • Thanks, I wasn't aware of this floating-point inconsistency while coding. My answer was being accepted as correct.
                  – Anirudh Thatipelli
                  Feb 27 at 6:06
















                • Thanks, I wasn't aware of this floating-point inconsistency while coding. My answer was being accepted as correct.
                  – Anirudh Thatipelli
                  Feb 27 at 6:06















                Thanks, I wasn't aware of this floating-point inconsistency while coding. My answer was being accepted as correct.
                – Anirudh Thatipelli
                Feb 27 at 6:06




                Thanks, I wasn't aware of this floating-point inconsistency while coding. My answer was being accepted as correct.
                – Anirudh Thatipelli
                Feb 27 at 6:06












                up vote
                1
                down vote













                1. The challenge defines the output of your function to be true or false. Java has the boolean primitive to model exactly that. Your method should return a boolean not an int that "means" true when it's not 0 (as would be the case for C).


                2. It's generally accepted best practice in java to define each variable (and member) on its own line. exp and base should be declared on separate lines.


                3. It's easier on your brain to keep track of things, if you're using them directly after you introduced them. That is generally referred to as "Declaring variables as close as possible to their usage".


                4. The vast majority of java conventions states that binary and ternary operators should have spaces around the operators. In your code that applies to +=, % and sometimes ==. Generally your formatting seems to try matching some standard, but isn't quite consistent, as evidenced by / having spacing when you calculate variable, but not when inside a a for-loop's head...

                  Above all you should strive to be consistent with formatting code. That makes it easier to read.


                5. Most Java conventions prefer opening braces to be on the same line as the block opening statement. That implies the same bracing style as you use for the method definition to extend to if, else and for statements.

                  In addition to that I highly recommend placing braces wherever possible.


                6. Lastly: the for-loops in if (A % 2 == 0) and else only differ by their initial value. Aside from that they are the same. Why did you opt for using a step-size of two with starts differing by one when you could've just as well iterated with a step-size of 1?






                share|improve this answer



























                  up vote
                  1
                  down vote













                  1. The challenge defines the output of your function to be true or false. Java has the boolean primitive to model exactly that. Your method should return a boolean not an int that "means" true when it's not 0 (as would be the case for C).


                  2. It's generally accepted best practice in java to define each variable (and member) on its own line. exp and base should be declared on separate lines.


                  3. It's easier on your brain to keep track of things, if you're using them directly after you introduced them. That is generally referred to as "Declaring variables as close as possible to their usage".


                  4. The vast majority of java conventions states that binary and ternary operators should have spaces around the operators. In your code that applies to +=, % and sometimes ==. Generally your formatting seems to try matching some standard, but isn't quite consistent, as evidenced by / having spacing when you calculate variable, but not when inside a a for-loop's head...

                    Above all you should strive to be consistent with formatting code. That makes it easier to read.


                  5. Most Java conventions prefer opening braces to be on the same line as the block opening statement. That implies the same bracing style as you use for the method definition to extend to if, else and for statements.

                    In addition to that I highly recommend placing braces wherever possible.


                  6. Lastly: the for-loops in if (A % 2 == 0) and else only differ by their initial value. Aside from that they are the same. Why did you opt for using a step-size of two with starts differing by one when you could've just as well iterated with a step-size of 1?






                  share|improve this answer

























                    up vote
                    1
                    down vote










                    up vote
                    1
                    down vote









                    1. The challenge defines the output of your function to be true or false. Java has the boolean primitive to model exactly that. Your method should return a boolean not an int that "means" true when it's not 0 (as would be the case for C).


                    2. It's generally accepted best practice in java to define each variable (and member) on its own line. exp and base should be declared on separate lines.


                    3. It's easier on your brain to keep track of things, if you're using them directly after you introduced them. That is generally referred to as "Declaring variables as close as possible to their usage".


                    4. The vast majority of java conventions states that binary and ternary operators should have spaces around the operators. In your code that applies to +=, % and sometimes ==. Generally your formatting seems to try matching some standard, but isn't quite consistent, as evidenced by / having spacing when you calculate variable, but not when inside a a for-loop's head...

                      Above all you should strive to be consistent with formatting code. That makes it easier to read.


                    5. Most Java conventions prefer opening braces to be on the same line as the block opening statement. That implies the same bracing style as you use for the method definition to extend to if, else and for statements.

                      In addition to that I highly recommend placing braces wherever possible.


                    6. Lastly: the for-loops in if (A % 2 == 0) and else only differ by their initial value. Aside from that they are the same. Why did you opt for using a step-size of two with starts differing by one when you could've just as well iterated with a step-size of 1?






                    share|improve this answer















                    1. The challenge defines the output of your function to be true or false. Java has the boolean primitive to model exactly that. Your method should return a boolean not an int that "means" true when it's not 0 (as would be the case for C).


                    2. It's generally accepted best practice in java to define each variable (and member) on its own line. exp and base should be declared on separate lines.


                    3. It's easier on your brain to keep track of things, if you're using them directly after you introduced them. That is generally referred to as "Declaring variables as close as possible to their usage".


                    4. The vast majority of java conventions states that binary and ternary operators should have spaces around the operators. In your code that applies to +=, % and sometimes ==. Generally your formatting seems to try matching some standard, but isn't quite consistent, as evidenced by / having spacing when you calculate variable, but not when inside a a for-loop's head...

                      Above all you should strive to be consistent with formatting code. That makes it easier to read.


                    5. Most Java conventions prefer opening braces to be on the same line as the block opening statement. That implies the same bracing style as you use for the method definition to extend to if, else and for statements.

                      In addition to that I highly recommend placing braces wherever possible.


                    6. Lastly: the for-loops in if (A % 2 == 0) and else only differ by their initial value. Aside from that they are the same. Why did you opt for using a step-size of two with starts differing by one when you could've just as well iterated with a step-size of 1?







                    share|improve this answer















                    share|improve this answer



                    share|improve this answer








                    edited Feb 27 at 22:12









                    mdfst13

                    16.8k42055




                    16.8k42055











                    answered Feb 26 at 22:48









                    Vogel612♦

                    20.9k345124




                    20.9k345124




















                        up vote
                        0
                        down vote













                        For a given number N, you do a loop over the potential base numbers A, and calculate the exponent P, checking whether it's integer. This way, you have to loop over a lot of numbers.



                        If you do it the other way round, with a loop over the potential exponents P, calculating the matching base A and checking that for an integer value, you only have to iterate from P=2 to P=30.



                        I didn't check if your code works - I have my doubts, especially with the "check for integer" part.




                        A few comments on your coding style:



                        Your method isPower() is meant to check if the given number can be represented as a power A^P. Instead of an int you should return a boolean (true or false instead of 1 or 0).



                        The naming of classes, methods, fields, variables and so on is crucial for the readability of code. They should reflect the thing they represent. So, isPower is a good name for a method that checks whether the number is a power. But names like variable don't help. Names like exp and base are good choices, but you only declare them and don't use them (any decent IDE will flag them as unused). One-letter names should be avoided as much as possible (with the exception of loop variables like i, j, or k).



                        There are naming conventions in Java, especially variables should always begin with a lowercase letter. Long-term Java developers will automatically understand anything that begins with uppercase as a class name, and have a hard time if in your code, the conventions don't apply.



                        Your indentation and placement of braces is unique. Following the usual style makes it easier to read your code and doesn't waste so much space (even the simple class presented here has lines too wide to fit into the space on this site).



                        Code like



                         if( A == 1)
                        return 1;


                        not surrounding the dependent statement with braces, is a maintenance risk. Imagine that later someone wants to add another statement here:



                         if( A == 1)
                        log.info("found a solution");
                        return 1;


                        That looks fine at a first glance, but effectively it's:



                         if( A == 1) 
                        log.info("found a solution");

                        return 1;


                        Not what you want, isn't it? So, I recommend to always use braces.



                        Write Javadoc comments at least for all public classes and methods.



                        After renaming, commenting and reformatting your code (but keeping your algorithm), we'd get:



                        /**
                        * Solution to the <a href=https://www.interviewbit.com/problems/power-of-two-integers/>
                        * Power of Two Integers</a> problem.
                        *
                        * @author your name
                        */
                        public class Solution

                        /**
                        * Check if <code>power</code> can be represented as <code>A^P</code>
                        * with A and P being integers, and P greater that 1.
                        * @param power the number under test
                        * @return true if <code>power</code> can be represented as <code>A^P</code>
                        */
                        public boolean isPower(int power)
                        if (power == 1)
                        return true;


                        if (power % 2 == 0)
                        for (int base = 2; base < power; base += 2)
                        double exp = Math.log(power) / Math.log(base);
                        double formattedExp = Double.parseDouble(String.format("%.6f", exp));

                        if ((formattedExp == Math.floor(formattedExp)) && !Double.isInfinite(formattedExp))
                        return true;


                        return false;

                        else
                        for (int base = 3; base < power / 2; base += 2)
                        double exp = Math.log(power) / Math.log(base);
                        double formattedExp = Double.parseDouble(String.format("%.6f", exp));

                        if ((formattedExp == Math.floor(formattedExp)) && !Double.isInfinite(formattedExp))
                        return true;


                        return false;








                        share|improve this answer



























                          up vote
                          0
                          down vote













                          For a given number N, you do a loop over the potential base numbers A, and calculate the exponent P, checking whether it's integer. This way, you have to loop over a lot of numbers.



                          If you do it the other way round, with a loop over the potential exponents P, calculating the matching base A and checking that for an integer value, you only have to iterate from P=2 to P=30.



                          I didn't check if your code works - I have my doubts, especially with the "check for integer" part.




                          A few comments on your coding style:



                          Your method isPower() is meant to check if the given number can be represented as a power A^P. Instead of an int you should return a boolean (true or false instead of 1 or 0).



                          The naming of classes, methods, fields, variables and so on is crucial for the readability of code. They should reflect the thing they represent. So, isPower is a good name for a method that checks whether the number is a power. But names like variable don't help. Names like exp and base are good choices, but you only declare them and don't use them (any decent IDE will flag them as unused). One-letter names should be avoided as much as possible (with the exception of loop variables like i, j, or k).



                          There are naming conventions in Java, especially variables should always begin with a lowercase letter. Long-term Java developers will automatically understand anything that begins with uppercase as a class name, and have a hard time if in your code, the conventions don't apply.



                          Your indentation and placement of braces is unique. Following the usual style makes it easier to read your code and doesn't waste so much space (even the simple class presented here has lines too wide to fit into the space on this site).



                          Code like



                           if( A == 1)
                          return 1;


                          not surrounding the dependent statement with braces, is a maintenance risk. Imagine that later someone wants to add another statement here:



                           if( A == 1)
                          log.info("found a solution");
                          return 1;


                          That looks fine at a first glance, but effectively it's:



                           if( A == 1) 
                          log.info("found a solution");

                          return 1;


                          Not what you want, isn't it? So, I recommend to always use braces.



                          Write Javadoc comments at least for all public classes and methods.



                          After renaming, commenting and reformatting your code (but keeping your algorithm), we'd get:



                          /**
                          * Solution to the <a href=https://www.interviewbit.com/problems/power-of-two-integers/>
                          * Power of Two Integers</a> problem.
                          *
                          * @author your name
                          */
                          public class Solution

                          /**
                          * Check if <code>power</code> can be represented as <code>A^P</code>
                          * with A and P being integers, and P greater that 1.
                          * @param power the number under test
                          * @return true if <code>power</code> can be represented as <code>A^P</code>
                          */
                          public boolean isPower(int power)
                          if (power == 1)
                          return true;


                          if (power % 2 == 0)
                          for (int base = 2; base < power; base += 2)
                          double exp = Math.log(power) / Math.log(base);
                          double formattedExp = Double.parseDouble(String.format("%.6f", exp));

                          if ((formattedExp == Math.floor(formattedExp)) && !Double.isInfinite(formattedExp))
                          return true;


                          return false;

                          else
                          for (int base = 3; base < power / 2; base += 2)
                          double exp = Math.log(power) / Math.log(base);
                          double formattedExp = Double.parseDouble(String.format("%.6f", exp));

                          if ((formattedExp == Math.floor(formattedExp)) && !Double.isInfinite(formattedExp))
                          return true;


                          return false;








                          share|improve this answer

























                            up vote
                            0
                            down vote










                            up vote
                            0
                            down vote









                            For a given number N, you do a loop over the potential base numbers A, and calculate the exponent P, checking whether it's integer. This way, you have to loop over a lot of numbers.



                            If you do it the other way round, with a loop over the potential exponents P, calculating the matching base A and checking that for an integer value, you only have to iterate from P=2 to P=30.



                            I didn't check if your code works - I have my doubts, especially with the "check for integer" part.




                            A few comments on your coding style:



                            Your method isPower() is meant to check if the given number can be represented as a power A^P. Instead of an int you should return a boolean (true or false instead of 1 or 0).



                            The naming of classes, methods, fields, variables and so on is crucial for the readability of code. They should reflect the thing they represent. So, isPower is a good name for a method that checks whether the number is a power. But names like variable don't help. Names like exp and base are good choices, but you only declare them and don't use them (any decent IDE will flag them as unused). One-letter names should be avoided as much as possible (with the exception of loop variables like i, j, or k).



                            There are naming conventions in Java, especially variables should always begin with a lowercase letter. Long-term Java developers will automatically understand anything that begins with uppercase as a class name, and have a hard time if in your code, the conventions don't apply.



                            Your indentation and placement of braces is unique. Following the usual style makes it easier to read your code and doesn't waste so much space (even the simple class presented here has lines too wide to fit into the space on this site).



                            Code like



                             if( A == 1)
                            return 1;


                            not surrounding the dependent statement with braces, is a maintenance risk. Imagine that later someone wants to add another statement here:



                             if( A == 1)
                            log.info("found a solution");
                            return 1;


                            That looks fine at a first glance, but effectively it's:



                             if( A == 1) 
                            log.info("found a solution");

                            return 1;


                            Not what you want, isn't it? So, I recommend to always use braces.



                            Write Javadoc comments at least for all public classes and methods.



                            After renaming, commenting and reformatting your code (but keeping your algorithm), we'd get:



                            /**
                            * Solution to the <a href=https://www.interviewbit.com/problems/power-of-two-integers/>
                            * Power of Two Integers</a> problem.
                            *
                            * @author your name
                            */
                            public class Solution

                            /**
                            * Check if <code>power</code> can be represented as <code>A^P</code>
                            * with A and P being integers, and P greater that 1.
                            * @param power the number under test
                            * @return true if <code>power</code> can be represented as <code>A^P</code>
                            */
                            public boolean isPower(int power)
                            if (power == 1)
                            return true;


                            if (power % 2 == 0)
                            for (int base = 2; base < power; base += 2)
                            double exp = Math.log(power) / Math.log(base);
                            double formattedExp = Double.parseDouble(String.format("%.6f", exp));

                            if ((formattedExp == Math.floor(formattedExp)) && !Double.isInfinite(formattedExp))
                            return true;


                            return false;

                            else
                            for (int base = 3; base < power / 2; base += 2)
                            double exp = Math.log(power) / Math.log(base);
                            double formattedExp = Double.parseDouble(String.format("%.6f", exp));

                            if ((formattedExp == Math.floor(formattedExp)) && !Double.isInfinite(formattedExp))
                            return true;


                            return false;








                            share|improve this answer















                            For a given number N, you do a loop over the potential base numbers A, and calculate the exponent P, checking whether it's integer. This way, you have to loop over a lot of numbers.



                            If you do it the other way round, with a loop over the potential exponents P, calculating the matching base A and checking that for an integer value, you only have to iterate from P=2 to P=30.



                            I didn't check if your code works - I have my doubts, especially with the "check for integer" part.




                            A few comments on your coding style:



                            Your method isPower() is meant to check if the given number can be represented as a power A^P. Instead of an int you should return a boolean (true or false instead of 1 or 0).



                            The naming of classes, methods, fields, variables and so on is crucial for the readability of code. They should reflect the thing they represent. So, isPower is a good name for a method that checks whether the number is a power. But names like variable don't help. Names like exp and base are good choices, but you only declare them and don't use them (any decent IDE will flag them as unused). One-letter names should be avoided as much as possible (with the exception of loop variables like i, j, or k).



                            There are naming conventions in Java, especially variables should always begin with a lowercase letter. Long-term Java developers will automatically understand anything that begins with uppercase as a class name, and have a hard time if in your code, the conventions don't apply.



                            Your indentation and placement of braces is unique. Following the usual style makes it easier to read your code and doesn't waste so much space (even the simple class presented here has lines too wide to fit into the space on this site).



                            Code like



                             if( A == 1)
                            return 1;


                            not surrounding the dependent statement with braces, is a maintenance risk. Imagine that later someone wants to add another statement here:



                             if( A == 1)
                            log.info("found a solution");
                            return 1;


                            That looks fine at a first glance, but effectively it's:



                             if( A == 1) 
                            log.info("found a solution");

                            return 1;


                            Not what you want, isn't it? So, I recommend to always use braces.



                            Write Javadoc comments at least for all public classes and methods.



                            After renaming, commenting and reformatting your code (but keeping your algorithm), we'd get:



                            /**
                            * Solution to the <a href=https://www.interviewbit.com/problems/power-of-two-integers/>
                            * Power of Two Integers</a> problem.
                            *
                            * @author your name
                            */
                            public class Solution

                            /**
                            * Check if <code>power</code> can be represented as <code>A^P</code>
                            * with A and P being integers, and P greater that 1.
                            * @param power the number under test
                            * @return true if <code>power</code> can be represented as <code>A^P</code>
                            */
                            public boolean isPower(int power)
                            if (power == 1)
                            return true;


                            if (power % 2 == 0)
                            for (int base = 2; base < power; base += 2)
                            double exp = Math.log(power) / Math.log(base);
                            double formattedExp = Double.parseDouble(String.format("%.6f", exp));

                            if ((formattedExp == Math.floor(formattedExp)) && !Double.isInfinite(formattedExp))
                            return true;


                            return false;

                            else
                            for (int base = 3; base < power / 2; base += 2)
                            double exp = Math.log(power) / Math.log(base);
                            double formattedExp = Double.parseDouble(String.format("%.6f", exp));

                            if ((formattedExp == Math.floor(formattedExp)) && !Double.isInfinite(formattedExp))
                            return true;


                            return false;









                            share|improve this answer















                            share|improve this answer



                            share|improve this answer








                            edited Feb 27 at 20:14


























                            answered Feb 26 at 20:57









                            Ralf Kleberhoff

                            70527




                            70527




















                                up vote
                                0
                                down vote













                                There are some valid points regarding coding style and floating point arithmetic, but I want to focus on improving the time complexity of the solution. From my experiments, it seems that simpler is better. Simply looping over bases and exponents yields a result which is >20x faster than the previous answers posted here.



                                public class Solution 

                                public static int pow2(int a, int b)
                                int re = 1;
                                while (b > 0)
                                if ((b & 1) == 1)
                                re *= a;

                                b >>= 1;
                                a *= a;

                                return re;


                                public boolean isPower(int n)
                                if (n < 4)
                                return n == 1;


                                for (int a = 2; a < Math.sqrt(n)+1; a++)
                                if (n % a*a == 0)
                                for (int p = (int) (Math.log(n)/Math.log(a)); p < 32; p++)
                                int result = pow2(a, p);
                                if (result == n)
                                return true;

                                if (result > n)
                                break;




                                return false;




                                Disclosure: I copied the pow2 function from here.



                                Explanation: since the input was a positive integer, we first create special cases for n<4. For every other value of n, test every value of a which is a suitable candidate. There's no need to check beyond sqrt(n), because the lowest exponent is p=2.



                                With some math, you can figure out that given the base a, the exponent p should be approximately log(n)/log(a). Since n fits within a signed 32-bit integer, we know that p<32.



                                Then we simply compute a^p and check if it is equal to n. Simple as that. This code outputs identical results for all values of n less than 100000 (that's how far I tested) compared to previous solutions in this thread.



                                Possible future improvements: remove all floating point arithmetic and instead use bit-shift operations to approximate the logarithm, and do a special case to see if n only has one bit set (e.g. 0b00100000), which implies that it is a power of 2.



                                EDIT: additional speedup



                                After some research, I concluded that reversing the search order would make the function faster. Since we know that 1<p<lg(n)+1, we can try all those values, and perform a binary search for the value of a.



                                public boolean isPower(int n) 
                                if (n < 4)
                                return n == 1;


                                int maxExponent = 0;
                                int tempN = n;
                                while (tempN > 0)
                                maxExponent++;
                                tempN >>= 1;

                                int low_a;
                                int high_a;
                                int temp_a;
                                int result;

                                for (int p = 2; p < maxExponent+1; p++)

                                low_a = 1;
                                high_a = 1<<(maxExponent/p+1);

                                while (high_a-low_a > 1)

                                temp_a = (low_a+high_a)/2;
                                result = pow2(temp_a, p);

                                if (result == n)
                                return true;

                                if (result < n)
                                low_a = temp_a;
                                else
                                high_a = temp_a;



                                return false;



                                Some included benchmarks:



                                Time to calculate isPower for every number between 1 and 10^5:
                                200_success' solution: 2.769842086 seconds
                                My previous solution: 0.108119151 seconds
                                My new solution: 0.034731273 seconds

                                Time to calculate isPower for every number between 1 and 10^6:
                                200_success' solution: ~30 seconds
                                My previous solution: 2.833582944 seconds
                                My new solution: 0.4383110970 seconds

                                Time to calculate isPower for every number between 10^9 and 10^9+10^4:
                                200_success' solution: not included
                                My previous solution: 1.3411200 seconds
                                My new solution: 0.014713117 seconds


                                From this benchmark we can see that the new algorithm is much faster for large values of n, being almost 100 times faster in the last benchmark.






                                share|improve this answer



























                                  up vote
                                  0
                                  down vote













                                  There are some valid points regarding coding style and floating point arithmetic, but I want to focus on improving the time complexity of the solution. From my experiments, it seems that simpler is better. Simply looping over bases and exponents yields a result which is >20x faster than the previous answers posted here.



                                  public class Solution 

                                  public static int pow2(int a, int b)
                                  int re = 1;
                                  while (b > 0)
                                  if ((b & 1) == 1)
                                  re *= a;

                                  b >>= 1;
                                  a *= a;

                                  return re;


                                  public boolean isPower(int n)
                                  if (n < 4)
                                  return n == 1;


                                  for (int a = 2; a < Math.sqrt(n)+1; a++)
                                  if (n % a*a == 0)
                                  for (int p = (int) (Math.log(n)/Math.log(a)); p < 32; p++)
                                  int result = pow2(a, p);
                                  if (result == n)
                                  return true;

                                  if (result > n)
                                  break;




                                  return false;




                                  Disclosure: I copied the pow2 function from here.



                                  Explanation: since the input was a positive integer, we first create special cases for n<4. For every other value of n, test every value of a which is a suitable candidate. There's no need to check beyond sqrt(n), because the lowest exponent is p=2.



                                  With some math, you can figure out that given the base a, the exponent p should be approximately log(n)/log(a). Since n fits within a signed 32-bit integer, we know that p<32.



                                  Then we simply compute a^p and check if it is equal to n. Simple as that. This code outputs identical results for all values of n less than 100000 (that's how far I tested) compared to previous solutions in this thread.



                                  Possible future improvements: remove all floating point arithmetic and instead use bit-shift operations to approximate the logarithm, and do a special case to see if n only has one bit set (e.g. 0b00100000), which implies that it is a power of 2.



                                  EDIT: additional speedup



                                  After some research, I concluded that reversing the search order would make the function faster. Since we know that 1<p<lg(n)+1, we can try all those values, and perform a binary search for the value of a.



                                  public boolean isPower(int n) 
                                  if (n < 4)
                                  return n == 1;


                                  int maxExponent = 0;
                                  int tempN = n;
                                  while (tempN > 0)
                                  maxExponent++;
                                  tempN >>= 1;

                                  int low_a;
                                  int high_a;
                                  int temp_a;
                                  int result;

                                  for (int p = 2; p < maxExponent+1; p++)

                                  low_a = 1;
                                  high_a = 1<<(maxExponent/p+1);

                                  while (high_a-low_a > 1)

                                  temp_a = (low_a+high_a)/2;
                                  result = pow2(temp_a, p);

                                  if (result == n)
                                  return true;

                                  if (result < n)
                                  low_a = temp_a;
                                  else
                                  high_a = temp_a;



                                  return false;



                                  Some included benchmarks:



                                  Time to calculate isPower for every number between 1 and 10^5:
                                  200_success' solution: 2.769842086 seconds
                                  My previous solution: 0.108119151 seconds
                                  My new solution: 0.034731273 seconds

                                  Time to calculate isPower for every number between 1 and 10^6:
                                  200_success' solution: ~30 seconds
                                  My previous solution: 2.833582944 seconds
                                  My new solution: 0.4383110970 seconds

                                  Time to calculate isPower for every number between 10^9 and 10^9+10^4:
                                  200_success' solution: not included
                                  My previous solution: 1.3411200 seconds
                                  My new solution: 0.014713117 seconds


                                  From this benchmark we can see that the new algorithm is much faster for large values of n, being almost 100 times faster in the last benchmark.






                                  share|improve this answer

























                                    up vote
                                    0
                                    down vote










                                    up vote
                                    0
                                    down vote









                                    There are some valid points regarding coding style and floating point arithmetic, but I want to focus on improving the time complexity of the solution. From my experiments, it seems that simpler is better. Simply looping over bases and exponents yields a result which is >20x faster than the previous answers posted here.



                                    public class Solution 

                                    public static int pow2(int a, int b)
                                    int re = 1;
                                    while (b > 0)
                                    if ((b & 1) == 1)
                                    re *= a;

                                    b >>= 1;
                                    a *= a;

                                    return re;


                                    public boolean isPower(int n)
                                    if (n < 4)
                                    return n == 1;


                                    for (int a = 2; a < Math.sqrt(n)+1; a++)
                                    if (n % a*a == 0)
                                    for (int p = (int) (Math.log(n)/Math.log(a)); p < 32; p++)
                                    int result = pow2(a, p);
                                    if (result == n)
                                    return true;

                                    if (result > n)
                                    break;




                                    return false;




                                    Disclosure: I copied the pow2 function from here.



                                    Explanation: since the input was a positive integer, we first create special cases for n<4. For every other value of n, test every value of a which is a suitable candidate. There's no need to check beyond sqrt(n), because the lowest exponent is p=2.



                                    With some math, you can figure out that given the base a, the exponent p should be approximately log(n)/log(a). Since n fits within a signed 32-bit integer, we know that p<32.



                                    Then we simply compute a^p and check if it is equal to n. Simple as that. This code outputs identical results for all values of n less than 100000 (that's how far I tested) compared to previous solutions in this thread.



                                    Possible future improvements: remove all floating point arithmetic and instead use bit-shift operations to approximate the logarithm, and do a special case to see if n only has one bit set (e.g. 0b00100000), which implies that it is a power of 2.



                                    EDIT: additional speedup



                                    After some research, I concluded that reversing the search order would make the function faster. Since we know that 1<p<lg(n)+1, we can try all those values, and perform a binary search for the value of a.



                                    public boolean isPower(int n) 
                                    if (n < 4)
                                    return n == 1;


                                    int maxExponent = 0;
                                    int tempN = n;
                                    while (tempN > 0)
                                    maxExponent++;
                                    tempN >>= 1;

                                    int low_a;
                                    int high_a;
                                    int temp_a;
                                    int result;

                                    for (int p = 2; p < maxExponent+1; p++)

                                    low_a = 1;
                                    high_a = 1<<(maxExponent/p+1);

                                    while (high_a-low_a > 1)

                                    temp_a = (low_a+high_a)/2;
                                    result = pow2(temp_a, p);

                                    if (result == n)
                                    return true;

                                    if (result < n)
                                    low_a = temp_a;
                                    else
                                    high_a = temp_a;



                                    return false;



                                    Some included benchmarks:



                                    Time to calculate isPower for every number between 1 and 10^5:
                                    200_success' solution: 2.769842086 seconds
                                    My previous solution: 0.108119151 seconds
                                    My new solution: 0.034731273 seconds

                                    Time to calculate isPower for every number between 1 and 10^6:
                                    200_success' solution: ~30 seconds
                                    My previous solution: 2.833582944 seconds
                                    My new solution: 0.4383110970 seconds

                                    Time to calculate isPower for every number between 10^9 and 10^9+10^4:
                                    200_success' solution: not included
                                    My previous solution: 1.3411200 seconds
                                    My new solution: 0.014713117 seconds


                                    From this benchmark we can see that the new algorithm is much faster for large values of n, being almost 100 times faster in the last benchmark.






                                    share|improve this answer















                                    There are some valid points regarding coding style and floating point arithmetic, but I want to focus on improving the time complexity of the solution. From my experiments, it seems that simpler is better. Simply looping over bases and exponents yields a result which is >20x faster than the previous answers posted here.



                                    public class Solution 

                                    public static int pow2(int a, int b)
                                    int re = 1;
                                    while (b > 0)
                                    if ((b & 1) == 1)
                                    re *= a;

                                    b >>= 1;
                                    a *= a;

                                    return re;


                                    public boolean isPower(int n)
                                    if (n < 4)
                                    return n == 1;


                                    for (int a = 2; a < Math.sqrt(n)+1; a++)
                                    if (n % a*a == 0)
                                    for (int p = (int) (Math.log(n)/Math.log(a)); p < 32; p++)
                                    int result = pow2(a, p);
                                    if (result == n)
                                    return true;

                                    if (result > n)
                                    break;




                                    return false;




                                    Disclosure: I copied the pow2 function from here.



                                    Explanation: since the input was a positive integer, we first create special cases for n<4. For every other value of n, test every value of a which is a suitable candidate. There's no need to check beyond sqrt(n), because the lowest exponent is p=2.



                                    With some math, you can figure out that given the base a, the exponent p should be approximately log(n)/log(a). Since n fits within a signed 32-bit integer, we know that p<32.



                                    Then we simply compute a^p and check if it is equal to n. Simple as that. This code outputs identical results for all values of n less than 100000 (that's how far I tested) compared to previous solutions in this thread.



                                    Possible future improvements: remove all floating point arithmetic and instead use bit-shift operations to approximate the logarithm, and do a special case to see if n only has one bit set (e.g. 0b00100000), which implies that it is a power of 2.



                                    EDIT: additional speedup



                                    After some research, I concluded that reversing the search order would make the function faster. Since we know that 1<p<lg(n)+1, we can try all those values, and perform a binary search for the value of a.



                                    public boolean isPower(int n) 
                                    if (n < 4)
                                    return n == 1;


                                    int maxExponent = 0;
                                    int tempN = n;
                                    while (tempN > 0)
                                    maxExponent++;
                                    tempN >>= 1;

                                    int low_a;
                                    int high_a;
                                    int temp_a;
                                    int result;

                                    for (int p = 2; p < maxExponent+1; p++)

                                    low_a = 1;
                                    high_a = 1<<(maxExponent/p+1);

                                    while (high_a-low_a > 1)

                                    temp_a = (low_a+high_a)/2;
                                    result = pow2(temp_a, p);

                                    if (result == n)
                                    return true;

                                    if (result < n)
                                    low_a = temp_a;
                                    else
                                    high_a = temp_a;



                                    return false;



                                    Some included benchmarks:



                                    Time to calculate isPower for every number between 1 and 10^5:
                                    200_success' solution: 2.769842086 seconds
                                    My previous solution: 0.108119151 seconds
                                    My new solution: 0.034731273 seconds

                                    Time to calculate isPower for every number between 1 and 10^6:
                                    200_success' solution: ~30 seconds
                                    My previous solution: 2.833582944 seconds
                                    My new solution: 0.4383110970 seconds

                                    Time to calculate isPower for every number between 10^9 and 10^9+10^4:
                                    200_success' solution: not included
                                    My previous solution: 1.3411200 seconds
                                    My new solution: 0.014713117 seconds


                                    From this benchmark we can see that the new algorithm is much faster for large values of n, being almost 100 times faster in the last benchmark.







                                    share|improve this answer















                                    share|improve this answer



                                    share|improve this answer








                                    edited Feb 28 at 14:12


























                                    answered Feb 28 at 12:43









                                    maxb

                                    896312




                                    896312






















                                         

                                        draft saved


                                        draft discarded


























                                         


                                        draft saved


                                        draft discarded














                                        StackExchange.ready(
                                        function ()
                                        StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f188392%2fpower-of-two-integers%23new-answer', 'question_page');

                                        );

                                        Post as a guest













































































                                        Popular posts from this blog

                                        Greedy Best First Search implementation in Rust

                                        Function to Return a JSON Like Objects Using VBA Collections and Arrays

                                        C++11 CLH Lock Implementation