Task:
In an array of N elements (N < 20) of the unsigned long long type find the maximal full square and print its index (starting from zero). If there are no full squares, print -1. If there is more than one maximal square, print the index of the first one.
Input data: standard input stream, where N is written on the first line on the second line the array elements with a space.
Output data: a number in a standard output stream
Code:
#include <stdio.h>
#include <math.h>
int main() {
unsigned short int n;
unsigned long long mass[20];
unsigned long long max = 0;
int max_index = -1;
scanf("%hu", &n);
if (n >= 20) {
do{
scanf("%hu", &n);
}while(n >= 20);
}
for (int i = 0; i < n; i++) {
scanf("%llu", &mass[i]);
long double root = (long double) sqrt(mass[i]);
if (root * root == mass[i]) {
if (mass[i] > max) {
max = mass[i];
max_index = i;
}
}
}
printf("%d\n", max_index);
return 0;
}
I have this error while compiling
I tried to use different types of data but it was useless.
At least these issues:
Wrong compiler
Error message indicates OP is using a C++ compiler when a C compiler should be used for C code. Function overloading (part of C++) is not a standard feature of C.
Loss of precision
sqrt(mass[i])
can loses precision. unsigned long long
is at least a 64-bit type and converting that to double
(to preform the square root) can lose needed precision. Floating point math introduces rounding issues too that can lead to incorrect results for this integer problem. Better to use integer math than floating-point math for an integer problem.
Similar problems with root * root == mass[i]
Consider forming a unsigned long long isqrt_ull(unsigned long long x)
to find the square root.
Sample:
// Recursive version.
unsigned long long isqrt_ull(unsigned long long x) {
if (x < 2) {
return x;
}
unsigned long long s = isqrt_ull(x >> 2) << 1;
unsigned long long t = s + 1;
return (t > x / t) ? s : t;
}
Corner case: 0
If the array values are all 0, code reports -1 as mass[i] > max
is never true. Better as mass[i] > max || max_index == -1
Other minor issues
No need to test a new candidate for perfect square-ness unless it is greater than the prior max.
Avoid type proliferation: Use int
for reading the array size in this learner's exercise.
Check return value of scanf()
to know if input succeeded.
isqrt_ull()
is not a highly efficient integer square root routine. It is just there as a simple placeholder that does not suffer floating point issues yet handles unsigned long long
.