找到XXYY形式的所有完美正方形

时间:2011-01-09 13:05:15

标签: c++ algorithm

我必须找到XXYY形式的4位数字,它们是任何整数的正方形。我编写了这段代码,但是当我必须只过滤完美的整数时,它给出了所有数字的平方根。

我想只在它是一个整数时显示sqrt(z)

#include<math.h>
#include<iostream.h>
#include<conio.h>
void main()
{
 int x,y=4,z;
 clrscr();
 for(x=1;x<=9;x++)
 {
  z=11*(100*x+y);
  cout<<"\n"<<sqrt(z);

 }
 getch();
}

9 个答案:

答案 0 :(得分:3)

我可能会这样检查,因为我的政策是对数学函数的准确性感到偏执:

double root = sqrt(z);
int introot = floor(root + 0.5); // round to nearby integer
if ((introot * introot) == z) {  // integer arithmetic, so precise
    cout << introot << " == sqrt(" << z << ")\n";
}

double可以准确地表示我们关心的所有整数(就此而言,在大多数实现中,它可以精确地表示int的所有值)。它还具有足够的精度来区分我们关心的所有整数sqrt(x)sqrt(x+1)。 sqrt(10000) - sqrt(9999)是0.005,所以我们只需要5位小数的精度来避免误报,因为非整数平方根不能比整数更接近。因此,良好的sqrt实施可以足够准确,(int)root == root本身可以完成这项工作。

但是,该标准未指定sqrt和其他数学函数的准确性。在C99中,这在5.2.4.2.2 / 5中明确说明:我不确定C89或C ++是否使其明确。所以我不愿意排除结果可能是一个ulp左右。如果int(root) == root出现为sqrt(7744),那么sqrt将会出现假阴性,为87.9999999999999-ish

另外,double不能精确的数字要大得多(大约{{1}}可以精确表示的限制)。因此,我认为编写额外的两行代码比编写注释更容易解释为什么我认为数学函数在我关心的情况下是精确的: - )

答案 1 :(得分:2)

#include <iostream>
int main(int argc, char** argv) {
    for (int i = 32; i < 100; ++i) { 
        // anything less than 32 or greater than 100 
        // doesn't result in a 4-digit number
        int s = i*i;
        if (s/100%11==0 && s%100%11==0) {
            std::cout << i << '\t' << s << std::endl;
        }
    }
}

http://ideone.com/1Bn77

答案 2 :(得分:2)

绝对没有需要在此任务中涉及浮点数学。这是一段有效的代码,可以为您完成这项工作。

由于你的号码必须是一个完美的正方形,所以只能检查前面的完美正方形而不是所有四位数字,过滤掉非正方形(就像你在第一次切换天真的解决方案中所做的那样)。

使用整数而不是浮点值也可能更安全,因为在进行平方根计算时不必担心所有这些不准确性问题。

#include <stdio.h>
int main (void) {
    int d1, d2, d3, d4, sq, i = 32;
    while ((sq = i * i) <= 9999) {
        d1 = sq / 1000;
        d2 = (sq % 1000) / 100;
        d3 = (sq % 100) / 10;
        d4 = (sq % 10);
        if ((d1 == d2) && (d3 == d4))
            printf ("   %d\n", i * i);
        i++;
    }
    return 0;
}

它依赖于第一个四位数的完美平方为32 * 321024(31 2 为961)的事实。因此它检查32 2 ,33 2 ,34 2 ,依此类推,直到超过四位数限制(一个为100 < sup> 2 总共69种可能性,而天真的解决方案将检查大约9000种可能性。

然后,对于每种可能性,它会检查最终XXYY要求的数字,为您提供单一答案:

7744

答案 3 :(得分:2)

我们可以注意到

  • 1 + 3 = 2 ^ 2
  • 1 + 3 + 5 = 3 ^ 2,
  • 1 + 3 + 5 + 7 = 4 ^ 2,

即。 sum(1 + 3 + ... (2N + 1))任何N都是正方形。 (这很容易证明)

现在我们可以在[0000, 9999]中生成所有正方形,并检查每个正方形是否为XXYY。

答案 4 :(得分:1)

虽然我闻到了一个家庭作业问题,但这里有一些指导。 这个解决方案的问题在于你采用平方根,它引入了浮点运算和导致精确数学的问题。你可以通过以下方式来实现目标:

double epsilon = 0.00001;
if ((z % 1.0) < epsilon || (z % 1.0) + epsilon > 1) {
    // it's probably an integer
}

重写此算法可能值得您花时间通过测试不断增加的数字的平方来检查数字是否符合该格式。您需要测试的最高数字是您正在寻找的最高完美正方形的平方根。即sqrt(9988)= 99.93 ...所以你最多只需测试100个数字。我认为你可能测试的最低数字是1122,所以你实际上可以从34开始计算。

甚至有更好的解决方案涉及分解(以及使用模运算符) 但我认为现在这些都是足够的暗示。 ; - )

答案 5 :(得分:0)

要检查sqrt(x)是否为整数,请将其与其覆盖值进行比较:

sqrt(x) == (int) sqrt(x)

然而,由于精度问题,这实际上是一种比较浮点值的坏方法。您应该始终考虑一个小错误组件:

abs(sqrt(x) - ((int) sqrt(x))) < 0.0000001

即使您进行了此修正,但当您听起来像输出sqrt(z)时,您的程序仍会输出z。您还应该遍历所有y值,而不是仅考虑y=4(注意y a也是0,与x不同。)

答案 6 :(得分:0)

你生成数字的方式是不正确 确实正确(我的不好)所以你需要的只是寻找方方法的正确方法。 :)

loop x: 1 to 9
  if(check_for_perfect_square(x*1100 + 44))
         print: x*1100 + 44

请点击此处了解如何找到合适的方格Perfect square and perfect cube

答案 7 :(得分:0)

I want to show the sqrt(z) only when it is integer.

double result = sqrt( 25); // Took 25 as an example. Run this in a loop varying sqrt
                           // parameter
int checkResult = result;
if ( checkResult == result )
    std::cout << "perfect Square" ;
else
    std::cout << "not perfect square" ;

答案 8 :(得分:0)

你不需要采取平方根。请注意,您可以按升序轻松生成所有整数方块和所有数字XXYY。所以你只需要通过每个序列,寻找匹配:

 int n = 0 ;
 int X = 1, Y = 0 ; // Set X=0 here to alow the solution 0000
 while (X < 10) {
   int nSquared = n * n ;
   int XXYY = 1100 * X + 11 * Y ;

   // Output them if they are equal
   if (nSquared == XXYY) cout << XXYY << endl ;

   // Increment the smaller of the two
   if (nSquared <= XXYY) n++ ;
   else if (Y < 9) Y++ ;
   else { Y = 0 ; X++ ; }
   }