Алгоритм на странице Википедии не проверяет, равны ли знаменатели какого-либо из целочисленных делений нулю.
Я протестировал слегка измененную версию этого (я такжеиспользовал C ++, что, вероятно, на самом деле и использовал OP, поскольку в комментариях упоминается об использовании «функции gcd C ++ STL») для первых 32768 значений N, получая:
N: 3 Q == 0 in the first division
N: 5 Q == 0 in the first division
N: 7 Q == 0 in the first division
N: 11 Q == 0 in the first division
N: 27 Q == 0 in the first division
N: 363 Q == 0 in the first division
N: 867 Q == 0 in the first division
N: 1445 Q == 0 in the first division
N: 5043 Q == 0 in the first division
N: 6845 Q == 0 in the first division
N: 7803 Q == 0 in the first division
N: 10443 Q == 0 in the first division
N: 11163 Q == 0 in the first division
N: 13467 Q == 0 in the first division
N: 14283 Q == 0 in the first division
N: 18491 Q == 0 in the first division
N: 18723 Q == 0 in the first division
N: 23763 Q == 0 in the first division
N: 30603 Q == 0 in the first division
N: 31827 Q == 0 in the first division
You 'Заметим, что первые случаи являются простыми числами и также присутствуют в массиве multipliers
.
Перед внутренним циклом, в котором выполняется первое деление, переменная Q
вычисляется по существу как
D = multiplier[k]*N;
Po = sqrtl(D);
Q = D - Po*Po;
Итак, Q
- ноль, когда D
- идеальный квадрат.Вы можете позаботиться об этих угловых случаях, добавив несколько строк код :
const uint64_t multiplier[] = {
1, 3, 5, 7, 11, 3*5, 3*7, 3*11, 5*7, 5*11, 7*11, 3*5*7,
3*5*11, 3*7*11, 5*7*11, 3*5*7*11
};
const uint64_t results[] = {
1, 0, 0, 0, 0, 3, 3, 3, 5, 5, 7, 3, 3, 3, 5, 3
};
// ... inside the k loop
if ( multiplier[k] == N )
return results[k];
// ... calculate Q as before
if (Q == 0)
return std::gcd(multiplier[k], N);
// ... rest of the loop