Есть некоторые числовые проблемы с этой строкой в вашем коде
temp = sqrt((double)(x*x-i*i)); // where 'temp', 'x' and 'i' are int
И x*x
, и i*i
могут переполниться. Не имеет значения, приведен ли результат к double
, потому что это происходит после выполнения продукта. Вы должны использовать больший тип, например long long
и привести значения перед умножением. В этом случае приведение к double
может даже привести к некоторым ошибкам округления.
Присвоение результата sqrt
int
также может привести к некоторым нежелательным ошибкам округления. Вы можете использовать round()
для их предотвращения.
В этом конкретном случае вместо этого вы можете избежать sqrt
и сохранить некоторые итерации, используя другой алгоритм:
#include <stdbool.h>
static inline long long sq(int x)
{
return (long long)x * x;
}
bool is_nonhypotenuse(int x)
{
long long square_x = sq(x);
// Meet in the middle, instead of going up to x
for (int i = 1, j = x - 1; i <= j; i++)
{
long long square_j, target = square_x - sq(i);
// Iterates, instead of calculating the square root
while ( (square_j = sq(j)) > target )
--j;
if ( square_j == target )
return false;
}
return true;
}
Редактировать
Другая проблема (вероятно, самая важная, учитывая входные данные) заключается в функции, используемой для вычисления степеней 2.
int powTwo(int exp) {
int x=2; // <-- It should start from 1, here
for (;exp>0;exp--) {
x*=2;
}
return (x); // <-- Effectively returns 2^(exp + 1)
}
Вместо этого вы можете рассмотреть этот более общий подход.
long long int_pow(int base, int exp)
{
long long result = 1;
while ( exp )
{
if (exp & 1)
result *= base;
exp /= 2;
base *= base;
}
return result;
}
Или, учитывая, что основание равно 2, просто используйте сдвиг битов
int R = b * b - (1 << a);
С этими изменениями ваша программа должна вывестижелаемое значение. См. Например здесь .