Check if BigInteger is not a perfect square

后端 未结 6 1661
悲&欢浪女
悲&欢浪女 2020-12-29 14:12

I have a BigInteger value, let\'s say it is 282 and is inside the variable x. I now want to write a while loop that states:

while b2 isn\'t a perfect square:         


        
相关标签:
6条回答
  • 2020-12-29 14:38
    using System.Numerics; // needed for BigInteger
    
    /* Variables */
    BigInteger a, b, b2, n, p, q;
    int flag;
    
    /* Assign Data */
    n = 10147;
    a = iSqrt(n);
    
    /* Algorithm */
    do
    {   a = a + 1;
        b2 = (a * a) – n;
        b = iSqrt(b2);
        flag = BigInteger.Compare(b * b, b2);
    } while(flag != 0);
    
    /* Output Data */
    p = a + b;
    q = a – b;
    
    
    /* Method */
        private static BigInteger iSqrt(BigInteger num)
        { // Finds the integer square root of a positive number            
            if (0 == num) { return 0; }     // Avoid zero divide            
            BigInteger n = (num / 2) + 1;   // Initial estimate, never low            
            BigInteger n1 = (n + (num / n)) / 2;
            while (n1 < n)
            {   n = n1;
                n1 = (n + (num / n)) / 2;
            }
            return n;
        } // end iSqrt()
    
    0 讨论(0)
  • 2020-12-29 14:45

    DON'T use this...

     BigInteger n = ...;
     double n_as_double = n.doubleValue();
     double n_sqrt = Math.sqrt(n_as_double);
     BigInteger n_sqrt_as_int = new BigDecimal(n_sqrt).toBigInteger();
     if (n_sqrt_as_int.pow(2).equals(n)) {
      // number is perfect square
     }
    

    As Christian Semrau commented below - this doesn't work. I am sorry for posting incorrect answer.

    0 讨论(0)
  • 2020-12-29 14:49

    I found a sqrt method used here, and simplified the square test.

    private static final BigInteger b100 = new BigInteger("100");
    private static final boolean[] isSquareResidue;
    static{
        isSquareResidue = new boolean[100];
        for(int i =0;i<100;i++){
            isSquareResidue[(i*i)%100]=true;
        }
    }
    
    public static boolean isSquare(final BigInteger r) {
        final int y = (int) r.mod(b100).longValue();
        boolean check = false;
        if (isSquareResidue[y]) {
            final BigInteger temp = sqrt(r);
            if (r.compareTo(temp.pow(2)) == 0) {
                check = true;
            }
        }
        return check;
    }
    
    public static BigInteger sqrt(final BigInteger val) {
        final BigInteger two = BigInteger.valueOf(2);
        BigInteger a = BigInteger.ONE.shiftLeft(val.bitLength() / 2);
        BigInteger b;
        do {
            b = val.divide(a);
            a = (a.add(b)).divide(two);
        } while (a.subtract(b).abs().compareTo(two) >= 0);
        return a;
    }
    
    0 讨论(0)
  • 2020-12-29 14:50

    I use this:

    SQRPerfect is the number I want to test: This also has a nice Square Root so you get to use this as well if you need it seperately. You can get a little speed up if you bring the Square Root inside the Perfect Square test, but I like having both functions.

    if(PerfectSQR(SQRPerfect)){
        Do Something
    }
    
    
    public static Boolean PerfectSQR(BigInteger A) {
        Boolean p=false;
        BigInteger B=SQRT(A);
        BigInteger C=B.multiply(B);
        if (C.equals(A)){p=true;}
        return p;
    }
    
    public static BigInteger SQRT(BigInteger A) {
        BigInteger a=BigInteger.ONE,b=A.shiftRight(5).add(BigInteger.valueOf(8));
        while ((b.compareTo(a))>=0){
            BigInteger mid = a.add(b).shiftRight(1);
            if (mid.multiply(mid).compareTo(A)>0){b=mid.subtract(BigInteger.ONE);}
            else{a=mid.add(BigInteger.ONE);}
        }
      return a.subtract(BigInteger.ONE);
    }
    
    0 讨论(0)
  • 2020-12-29 14:56

    Compute the integer square root, then check that its square is your number. Here is my method of computing the square root using Heron's method:

    private static final BigInteger TWO = BigInteger.valueOf(2);
    
    
    /**
     * Computes the integer square root of a number.
     *
     * @param n  The number.
     *
     * @return  The integer square root, i.e. the largest number whose square
     *     doesn't exceed n.
     */
    public static BigInteger sqrt(BigInteger n)
    {
        if (n.signum() >= 0)
        {
            final int bitLength = n.bitLength();
            BigInteger root = BigInteger.ONE.shiftLeft(bitLength / 2);
    
            while (!isSqrt(n, root))
            {
                root = root.add(n.divide(root)).divide(TWO);
            }
            return root;
        }
        else
        {
            throw new ArithmeticException("square root of negative number");
        }
    }
    
    
    private static boolean isSqrt(BigInteger n, BigInteger root)
    {
        final BigInteger lowerBound = root.pow(2);
        final BigInteger upperBound = root.add(BigInteger.ONE).pow(2);
        return lowerBound.compareTo(n) <= 0
            && n.compareTo(upperBound) < 0;
    }
    
    0 讨论(0)
  • 2020-12-29 14:57
    private static boolean isSqrt(BigInteger n, BigInteger root)
    {
        final BigInteger lowerBound = root.pow(2);
        final BigInteger upperBound = root.add(BigInteger.ONE).pow(2);
        return lowerBound.compareTo(n) <= 0
            && n.compareTo(upperBound) < 0;
    }
    

    I tried the above using JavaScript BigInt:

    function isPerfectSqrt(n, root) {
      const lowerBound = root**2n;
      const upperBound = (root+1n)**2n
      return lowerBound <= n && n < upperBound;
    }
    

    And found it was only about 60% as fast (in Node V8) as the one-liner:

    function isPerfectSqrt(n, root) {
      return (n/root === root && n%root === 0n)
    }
    
    0 讨论(0)
提交回复
热议问题