Fastest way to determine if an integer's square root is an integer

前端 未结 30 2277
心在旅途
心在旅途 2020-11-22 02:17

I\'m looking for the fastest way to determine if a long value is a perfect square (i.e. its square root is another integer):

  1. I\'ve done it the ea
30条回答
  •  南旧
    南旧 (楼主)
    2020-11-22 02:43

    I checked all of the possible results when the last n bits of a square is observed. By successively examining more bits, up to 5/6th of inputs can be eliminated. I actually designed this to implement Fermat's Factorization algorithm, and it is very fast there.

    public static boolean isSquare(final long val) {
       if ((val & 2) == 2 || (val & 7) == 5) {
         return false;
       }
       if ((val & 11) == 8 || (val & 31) == 20) {
         return false;
       }
    
       if ((val & 47) == 32 || (val & 127) == 80) {
         return false;
       }
    
       if ((val & 191) == 128 || (val & 511) == 320) {
         return false;
       }
    
       // if((val & a == b) || (val & c == d){
       //   return false;
       // }
    
       if (!modSq[(int) (val % modSq.length)]) {
            return false;
       }
    
       final long root = (long) Math.sqrt(val);
       return root * root == val;
    }
    

    The last bit of pseudocode can be used to extend the tests to eliminate more values. The tests above are for k = 0, 1, 2, 3

  • a is of the form (3 << 2k) - 1
  • b is of the form (2 << 2k)
  • c is of the form (2 << 2k + 2) - 1
  • d is of the form (2 << 2k - 1) * 10

    It first tests whether it has a square residual with moduli of power of two, then it tests based on a final modulus, then it uses the Math.sqrt to do a final test. I came up with the idea from the top post, and attempted to extend upon it. I appreciate any comments or suggestions.

    Update: Using the test by a modulus, (modSq) and a modulus base of 44352, my test runs in 96% of the time of the one in the OP's update for numbers up to 1,000,000,000.

提交回复
热议问题