完全平方数和完全立方数

11

C++中是否有预定义的函数用于检查一个数是否是某个数的平方或立方。

9个回答

21
不,但编写一个很容易:
bool is_perfect_square(int n) {
    if (n < 0)
        return false;
    int root(round(sqrt(n)));
    return n == root * root;
}

bool is_perfect_cube(int n) {
    int root(round(cbrt(n)));
    return n == root * root * root;
}

4
由于浮点数误差的存在,这种方法并不总是可行:如果 sqrt()cbrt() 恰好返回比实际根小 epsilon ,那么将其转换为整数将会截断该值,检查会失败。要完全防范这种情况,您还需要检查平方根情况下的 n ==(root +1)*(root +1) 或者立方根情况下的 n ==(root +1)*(root +1)*(root +1) - Adam Rosenfield
48
天啊,这让我头疼。我一直在寻找“根”函数,直到意识到你只是在初始化一个整数……我非常不喜欢你的编码风格。 - mpen
4
@Mark:你可以尽情不喜欢,但这是C++中“更标准”的初始化方式。我想它被称为“构造函数语法”之类的东西。也就是说,如果你正在构建一个需要多个构造参数的对象,你必须使用该语法。我不喜欢为数字类型做特殊例外,所以我也对它们使用构造函数语法。 - C. K. Young
6
哦天啊,我刚回到这个问题并试着留下同样的评论,然后注意到别人已经留了,于是试图点赞但找不到上箭头,然后看了一下用户,发现那是我自己。检查abs(root-round(root)) <= epsilon难道不比乘法更快吗? - mpen
2
这被称为直接初始化。但是,花括号初始化比使用括号更受欢迎,因为它消除了最令人烦恼的解析问题。 - stillanoob
显示剩余3条评论

6

sqrt(x), 通常可以写成 pow(x, 1./2) 或者 pow(x, 1./3)

例如:

int n = 9;
int a = (int) sqrt((double) n);
if(a * a == n || (a+1) * (a+1) == n)  // in case of an off-by-one float error
    cout << "It's a square!\n";

编辑:或者通用的:

bool is_nth_power(int a, int n) {
  if(n <= 0)
    return false;
  if(a < 0 && n % 2 == 0)
    return false;
  a = abs(a);

  int b = pow(a, 1. / n);
  return pow((double) b, n) == a || pow((double) (b+1), n) == a;
}

2
使用 pow(x, 1./3) 的问题在于,1/3 在浮点数中没有精确的表示方法,因此你并不是“真正”获得了立方根。 C99 及以后版本拥有 cbrt 函数,应该能更好地获取立方根。 - C. K. Young
我想是的。但是pow更容易推广,并且很容易纠正浮点误差。 - Jesse Beder

2
不,没有标准的 C 或 C++ 函数来检查整数是否是完全平方或完全立方体。
如果您想要快速并避免使用大多数答案中提到的浮点/双精度例程,则可以编写一个只使用整数的二进制搜索。 如果您可以找到一个 n,使得n^2 < m < (n+1)^2,则m不是完全平方数。 如果 m 是完全平方数,则您将找到一个 n,使得n^2=m。该问题在此处进行了讨论。

1

试试这个:

#include<math.h>
int isperfect(long n)
{
    double xp=sqrt((double)n);
    if(n==(xp*xp))
        return 1;
    else
        return 0;
}

1
最高效的答案可能是这个。
    int x=sqrt(num)
    if(sqrt(num)>x){
    Then its not a square root}
    else{it is a perfect square}

这种方法有效是因为x是一个整数,它会舍去小数部分,只存储整数部分。如果一个数字是一个整数的完全平方数,它的平方根将是一个整数,因此x和sqrt(x)将相等。


0

为了识别平方数,我在Java中尝试了这个算法。只需稍微改变语法,您也可以在C++中实现它。 逻辑是,每两个连续的完全平方数之间的差值增加2。Diff(1,4)=3,Diff(4,9)=5,Diff(9,16)=7,Diff(16,25)=9......以此类推。 我们可以利用这种现象来识别完全平方数。 Java代码如下:

    boolean isSquare(int num){
         int  initdiff = 3;
         int squarenum = 1;
         boolean flag = false;
         boolean square = false;
         while(flag != true){

                if(squarenum == num){

                    flag = true;
                    square = true;

                }else{

                    square = false;
                 }
                if(squarenum > num){

                    flag = true;
                }
            squarenum = squarenum + initdiff;
            initdiff = initdiff + 2;
   }
              return square;
 }  

为了使方块的识别更快,我们可以利用另一个现象,即完全平方数递归数字之和始终为1、4、7或9。 因此,一个更快的代码可以是...
  int recursiveSum(int num){
     int sum = 0;   
     while(num != 0){
     sum = sum + num%10;
     num = num/10;         
     }
     if(sum/10 != 0){         
        return recursiveSum(sum);     
     }
     else{
         return sum;
     }

 }
  boolean isSquare(int num){
         int  initdiff = 3;
         int squarenum = 1;
         boolean flag = false;
         boolean square = false;
         while(flag != true){

                if(squarenum == num){

                    flag = true;
                    square = true;

                }else{

                    square = false;
                 }
                if(squarenum > num){

                    flag = true;
                }
            squarenum = squarenum + initdiff;
            initdiff = initdiff + 2;
   }
              return square;
 }  

   boolean isCompleteSquare(int a){
    // System.out.println(recursiveSum(a));
     if(recursiveSum(a)==1 || recursiveSum(a)==4 || recursiveSum(a)==7 || recursiveSum(a)==9){

         if(isSquare(a)){

             return true;

         }else{
             return false;
         }


     }else{

         return false;


     }

  }

-1

我们可以使用内置的truc函数 -

#include <math.h>

// For perfect square
bool is_perfect_sq(double n) {
    double r = sqrt(n);
    return !(r - trunc(r));
}

// For perfect cube
bool is_perfect_cube(double n) {
    double r = cbrt(n);
    return !(r - trunc(r));
}

27的立方根检查失败。 - General Grievance

-1

对于完全平方数,你也可以这样做:

if(sqrt(n)==floor(sqrt(n)))
    return true;
else
    return false;

对于完全立方数,您可以:

if(cbrt(n)==floor(cbrt(n)))
    return true;
else
    return false;

希望这能帮到你。

如果这是“关于返回”的话,为什么不只是return sqrt(n)==floor(sqrt(n))?(为什么更喜欢floor而不是round?)然后,有int r = round(cbrt(n)); return n == r*r*r - 这些都不是“预定义的”,留给我们2016年的知识:Chris' answer - greybeard
由于浮点数舍入,这不是一个好的立方体检查方法。这将在 n == 27 失败:在线尝试! - General Grievance

-2
bool isSquare(int n) {
    return floor(sqrt(n)) == ceil(sqrt(n));
}

bool isQube(int n) {
    return floor(cbrt(n)) == ceil(cbrt(n));
}

你的立方根检查器在某些值(如27)上失败了。 - General Grievance
请不要仅仅发布代码作为答案,还要提供解释您的代码是如何解决问题的。带有解释的答案通常更有帮助和更高质量,并且更有可能吸引赞同。 - Mark Rotteveel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接