确定平方根是否为整数

时间:2014-03-07 00:28:08

标签: c++ arrays loops math sqrt

在我的程序中,我试图将find作为数字600851475143的最大素数因子。我已经创建了一个for循环,它确定了该数字的所有因子并将它们存储在向量数组中。我遇到的问题是我不知道如何确定因子是否可以是平方根并且给出整数而不是小数。到目前为止我的代码是:

#include <iostream>
#include <vector>
#include <math.h>

using namespace std;
vector <int> factors;

int main()
{
    double num = 600851475143;
    for (int i=1; i<=num; i++)
    {
        if (fmod(num,i)==0)
        {
            factors.push_back(i);
        }
    }

     for (int i=0; i<factors.size(); i++)
     {
         if (sqrt(factor[i]))                      // ??? 
     }
}

有人可以通过我的if语句告诉我如何判断数字是否可以平方根?

7 个答案:

答案 0 :(得分:10)

int s = sqrt(factor[i]);
if ((s * s) == factor[i]) 

正如霍布斯在评论中指出的那样,

  

假设double是通常的64位IEEE-754双精度浮点数,对于小于2 ^ 53的值,一个double和下一个可表示的double之间的差值小于或等于1.高于2 ^ 53,精度比整数差。

因此,如果您的int是32位,那么您是安全的。如果你必须处理大于2 ^ 53的数字,你可能会有一些精确错误。

答案 1 :(得分:3)

以下内容应该有效。它利用整数截断。

if (int (sqrt(factor[i])) * int (sqrt(factor[i])) == factor[i])

这是有效的,因为非方数的平方根是小数。通过转换为整数,可以删除double的小数部分。一旦你将它平方,它就不再等于原始的平方根。

答案 2 :(得分:3)

完美的正方形只能在基数16的0,1,4或9中结束,所以对于75%的输入(假设它们是均匀分布的),你可以避免调用平方根来换取一些非常快的有点笨拙。

int isPerfectSquare(int n)
{
    int h = n & 0xF;  // h is the last hex "digit"
    if (h > 9)
        return 0;
    // Use lazy evaluation to jump out of the if statement as soon as possible
    if (h != 2 && h != 3 && h != 5 && h != 6 && h != 7 && h != 8)
    {
        int t = (int) floor( sqrt((double) n) + 0.5 );
        return t*t == n;
    }
    return 0;
}

用法:

for ( int i = 0; i < factors.size(); i++) {
   if ( isPerfectSquare( factor[ i]))
     //...
}

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

答案 3 :(得分:2)

与cero比较时,您还必须考虑舍入误差。如果您的编译器支持c ++ 11,您可以使用std :: round,如果没有,您可以自己完成(here

#include <iostream>
#include <vector>
#include <math.h>

using namespace std;
vector <int> factors;

int main()
{
    double num = 600851475143;
    for (int i=1; i<=num; i++)
    {
        if (round(fmod(num,i))==0)
        {
            factors.push_back(i);
        }
    }

     for (int i=0; i<factors.size(); i++)
     {
         int s = sqrt(factor[i]);
         if ((s * s) == factor[i])  
     }
}

答案 4 :(得分:0)

你问的是错误的问题。你的算法错了。 (好吧,并非完全如此,但如果要按照提出的想法进行纠正,那将是非常低效的。)使用您的方法,您还需要递归地检查立方体,第五权力和所有其他主要权力。例如,尝试找到5120 = 5 * 2 ^ 10的所有因子。


更简单的方法是通过划分

来删除一个因子
num=num/i

如果它不再是一个因素,只会增加i。然后,如果迭代遇到一些i = j ^ 2或i = j ^ 3,...,则所有因子j(如果有的话)在早期阶段已经被删除,当时我有值j,并且在因子数组。


你也可以提到这是来自 Euler项目,问题3 。然后你可能会找到最近的讨论&#34; advice on how to make my algorithm faster&#34;其中讨论了更有效的分解算法变体。

答案 5 :(得分:0)

这是我编写的一个简单的C ++函数,用于确定数字是否具有整数平方根:

bool has_sqrtroot(int n)
{
    double sqrtroot=sqrt(n);
    double flr=floor(sqrtroot);
    if(abs(sqrtroot - flr) <= 1e-9)
        return true;

    return false;
}

答案 6 :(得分:0)

由于 sqrt() 函数使用浮点数,所以最好避免使用它的返回值(浮点计算偶尔会给出错误的结果,因为精度错误)。相反,您可以编写一个函数 - isSquareNumber(int n),它将决定数字是否为平方数,并且整个计算将以整数完成。

bool isSquareNumber(int n){
    int l=1, h=n;
    while(l<=h){
        int m = (l+h) / 2;
        if(m*m == n){
            return true;
        }else if(m*m > n){
            h = m-1;
        }else{
            l = m+1;
        }
    }
    return false;
}

int main()
{
   // ......
     for (int i=0; i<factors.size(); i++){
         if (isSquareNumber(factor[i]) == true){
              /// code
         }
     }
}