#include <stdio.h>
#include <stdlib.h>
int main() {
int i, j, n, maxi = 0;
printf("\n Introduce the number:\n");
scanf("%d", &n);
for (j = 1; j <= n; j++)
{
i = 0;
while (i < j) {
i++;
if (j == i * i) {
if (j > maxi) {
maxi = j;
printf("%d", maxi);
}
}
}
}
return 0;
}
我必须找到小于数字n
的最大完美平方,我成功找到了小于数字n
的所有完美平方,但是因为每次找到一个完美平方它显示了它,我想不出任何办法来比较找到的所有完美平方(或者至少这就是我认为的问题所在),所以我将不胜感激。我已经知道您也可以使用更简单的方法(例如下面的方法)解决此问题,如果您对解决方法有任何其他想法,我想听听他们的看法。
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main()
{
int n,j;
printf("\n Your number:\n");
scanf("%d",&n);
j=(int)sqrt(n);
printf("%d",j*j);
return 0;
}
答案 0 :(得分:2)
这里您只需要一个循环。检查是否i*i <= n
。如果是这样,请将maxi
设置为i*i
并递增i
:
int n, i = 1, sq = 1;
printf("\n Introduce the number:\n");
scanf("%d", &n);
while (i*i <= n) {
sq = i*i;
i++;
}
printf("sq=%d\n", sq);
答案 1 :(得分:1)
找到小于或等于n的最大完美平方
对于n>=0
,这类似于找到n
的整数平方根。
unsigned greatest_perfect_square(unsigned x) {
unsigned root = usqrt(x);
return root * root;
}
如果您还有其他解决方法的想法,我想听听他们的想法。
查找平方根的复杂度顺序为O(bit-width-of-type-n)。例如16次迭代。
#include <limits.h>
unsigned usqrt(unsigned x) {
unsigned y = 0;
unsigned xShifted = 0;
const unsigned MSBit = UINT_MAX - UINT_MAX/2;
// This constant relies on no padding and bit width even
const unsigned TwoBitCount_N = sizeof(x) * CHAR_BIT / 2;
for (unsigned TwoBitCount = TwoBitCount_N; TwoBitCount > 0; TwoBitCount--) {
// Shift `xShifted` 2 places left while shifting in the 2 MSbits of x
xShifted <<= 1;
if (x & MSBit) {
xShifted |= 1;
}
x <<= 1;
xShifted <<= 1;
if (x & MSBit) {
xShifted |= 1;
}
x <<= 1;
// Shift the answer 1 bit left
y <<= 1;
// Form test value as y*2 + 1
unsigned Test = (y << 1) | 1;
// If xShifted big enough ...
if (xShifted >= Test) {
xShifted -= Test;
// Increment answer
y |= 1;
}
}
return y;
}
OP的方法要慢得多。甚至内部循环也需要O(sqrt(n))时间。
注意:
OP的代码:j == i * i
可能会溢出,并且在j
较大时会导致错误的答案。
j/i == i
执行类似的测试,没有溢出。
@Jonathan Leffler建议使用Newton-Raphson approximation方法。下面一些经过严格测试的代码可以非常快速地运行,通常只需进行几次迭代。
我怀疑这主要是O(log(bit-width-of-type-n))
,但是O(log(bit-width-of-type-n))
当然仍然是bit_width()
。
这两个功能都可以改进。
unsigned bit_width(unsigned x) {
unsigned width = 0;
while (x) {
x /= 2;
width++;
}
return width;
}
unsigned usqrt_NR(unsigned x) {
if (x == 0) {
return 0;
}
unsigned y = 1u << bit_width(x)/2;
unsigned y_previous;
unsigned diff;
unsigned diff1count = 0;;
do {
y_previous = y;
y = (y + x/y)/2;
diff = y_previous < y ? y - y_previous : y_previous - y;
if (diff == 1) diff1count++;
} while (diff > 1 || (diff == 1 && diff1count <= 1));
y = (y_previous + y)/2;
return y;
}
答案 2 :(得分:0)
这样可以最大程度地减少乘法次数:它会查找第一个大于n的正方形,这意味着紧接其前的完美正方形是解。
for (i = 1; i <= n; i++) {
if (i*i > n) {
break;
}
}
i--;
// i*i is your answer
在某些平台上,利用(i+1)*(i+1) = i*i + 2*i + 1
或换句话说,如果您已经拥有i ^ 2,则可以通过将i加两次来获得(i + 1)^ 2,并增加1;在开始时,0 ^ 2为0以启动循环。
for (i = 0, sq = 0; i < n; i++) {
sq += i; // Or on some platforms sq += i<<1 instead of two sums
sq += i; // Some compilers will auto-optimize "sq += 2*i" for the platform
sq++; // Or even sq += ((2*i)|1) as adding 1 to even numbers is OR'ing 1
if (sq > n) {
break;
}
// if sq is declared as signed integer, a possible overflow will
// show it as being negative. This way we can still get a "correct" result
// with i the smallest root that does not overflow.
// In 16-bit arithmetic this is 181, root of 32761; next square would be
// 33124 which cannot be represented in signed 16-bit space.
if (sq < 0) {
break;
}
}
// (i*i) is your answer