Checking if a number is perfect square?

后端 未结 8 2040
野趣味
野趣味 2021-02-10 01:10

I think there is a precision problem with the following code:

bool isPerfectSquare(long long n){
    long long squareRootN=(long long)(sqrt(n)+0.5);

    return          


        
相关标签:
8条回答
  • 2021-02-10 01:39

    Sqrt(4) could return 1.9999

    No, 4 and 2 are exactly representable as binary floating point numbers. No precision problems there.

    The problem is that long long has 64 bits of precision, but double has only 52, so all solutions that rely on calling sqrt(double) will start failing when you hit that limit. Here is a simple test program:

    #include <iostream>
    #include <math.h>
    #include <stdlib.h>
    
    bool isPerfectSquare(long long n)
    {
        double root = sqrt(n);
        return floor(root) == root;
    }
    
    void check(long long x)
    {
        if (!isPerfectSquare(x))
            std::cerr << x << " should be perfect\n", exit(1);
        if (isPerfectSquare(x-1))
            std::cerr << x-1 << " should NOT be perfect\n", exit(1);
        if (isPerfectSquare(x+1))
            std::cerr << x+1 << " should NOT be perfect\n", exit(1);
    }
    
    int main()
    {
        for (long long i = 2; i < 3037000499; ++i)
            check(i * i);
        std::cout << "all tests passed\n";
    }
    

    And here is the output on my computer:

    4503599627370497 should NOT be perfect
    

    Note that log(4503599627370497)/log(2) = 52. In case you don't care about numbers that large, you can use the simple solution that merely checks whether sqrt returns an integral result.

    0 讨论(0)
  • 2021-02-10 01:50

    mmmm don't use float/double for your true/false outcome (you'll end up having approximation problems) Much better the integer apporach:

       boolean is_square(long long n)
       {
          long long a=n;
          while (a*a>n)
          {
             a=div(a+div(n,a),2);
          }
          return a*a==n;
       }
    

    div() is the integer division without remainder (you can use GCD() in some ways)

    I know, I know... care must be taken for overflow issues

    0 讨论(0)
提交回复
热议问题